[转]5个JavaScript面试题
问题1:闭包
考虑下面的代码:
|
1
2
3
4
5
6
|
var nodes = document.getElementsByTagName('button');for (var i = 0; i < nodes.length; i++) { nodes[i].addEventListener('click', function() { console.log('You clicked element #' + i); });} |
请问,如果用户点击第一个和第四个按钮,控制台上会输出什么?为什么?
答案
上面代码的目的在于检测JavaScript的一个重要概念:闭包。对于每一个JavaScript开发者来说,如果你想在网页中编写5行以上的代码,那么准确理解和恰当使用闭包是非常重要的。如果你想开始学习或者只是想简单地温习一下闭包,那么我强烈建议你去阅读这个教程:Colin Ihrig 写的JavaScript Closures Demystified 。
好了,回到上面的代码。控制台会输出两次You clicked element #NODES_LENGTH,其中#NODES_LENGTH等于nodes内的元素个数。当for循环结束时,变量i的值等于nodes的长度。另外,由于i是在事件被添加时的函数作用域,因此变量i属于事件的闭包。由于闭包中变量的值不是静态的,因而i的值并不是事件被添加时所赋予的值(比如添加第一个按钮时i为0,第二个按钮时i为1)。当事件被执行时,控制台会输出变量i当前的值,即i等于nodes的长度。
问题2:闭包
修复上题的问题,使得点击第一个按钮时输出1,点击第二个按钮时输出2。
答案
有多种办法解决这个问题,下面我给出其中的两种。
第一个解决方案要用到一个IIFE来创建另外一个闭包,从而得到所希望的i的值。相应的代码如下:
|
1
2
3
4
5
6
7
8
|
var nodes = document.getElementsByTagName('button');for (var i = 0; i < nodes.length; i++) { nodes[i].addEventListener('click', (function(i) { return function() { console.log('You clicked element #' + i); } })(i));} |
另一个解决方案不使用IIFE,而是将函数移到循环的外面,代码如下:
|
1
2
3
4
5
6
7
8
9
10
|
function handlerWrapper(i) { return function() { console.log('You clicked element #' + i); }}var nodes = document.getElementsByTagName('button');for (var i = 0; i < nodes.length; i++) { nodes[i].addEventListener('click', handlerWrapper(i));} |
问题3:数据类型
考虑如下代码:
|
1
2
3
4
|
console.log(typeof null);console.log(typeof {});console.log(typeof []);console.log(typeof undefined); |
答案
这一个问题看起来似乎有点傻,但是它测试了typeof 操作符的知识。很多JavaScript开发者并没有意识到typeof的独特性。在本例中,控制台会输出下面的内容:
object
object
object
undefined
最让人吃惊的输出结果可能是第三个,许多开发者认为typeof [ ] 会返回Array。如果想测试变量值是否为数组,可以写下面的代码:
|
1
2
3
4
|
var myArray = [];if (myArray instanceof Array) { // do something...} |
问题4:事件循环
下面代码运行结果是什么?请解释。
|
1
2
3
4
5
6
7
|
function printing() { console.log(1); setTimeout(function() { console.log(2); }, 1000); setTimeout(function() { console.log(3); }, 0); console.log(4);}printing(); |
答案
输出结果:
1
4
3
2
要弄懂数字为何以这种顺序输出,你需要弄明白setTimeout()是干什么的,以及浏览器的事件循环工作原理。浏览器有一个事件循环用于检查事件队列,处理延迟的事件。UI事件(例如,点击,滚动等),Ajax回调,以及提供给setTimeout()和setInterval()的回调都会依次被事件循环处理。因此,当调用setTimeout()函数时,即使延迟的时间被设置为0,提供的回调也会被排队。回调会呆在队列中,直到指定的时间用完后,引擎开始执行动作(如果它在当前不执行其他的动作)。因此,即使setTimeout()回调被延迟0毫秒,它仍然会被排队,并且直到函数中其他非延迟的语句被执行完了之后,才会执行。
有了这些认识,理解输出结果为“4”就容易了,因为它是函数的第一句并且没有使用setTimeout()函数来延迟。接着输出“4”,因为它是没有被延迟的数字,也没有进行排队。然后,剩下了“2”,“3”,两者都被排队,但是前者需要等待一秒,后者等待0秒(这意味着引擎完成前两个输出之后马上进行)。这就解释了为什么“3”在“2”之前。
问题5:算法
写一个判断质数的isPrime()函数,当其为质数时返回true,否则返回false。
答案
我认为这是在面试中最常问到的一个问题。尽管这个问题反复出现并且也很简单,但是从候选人提供的答案中能很好地看出候选人的数学和算法能力水平。
首先, 因为JavaScript不同于C或者Java,因此你不能信任传递来的数据类型。如果面试官没有明确地告诉你,你应该询问他是否需要做输入检查,还是不进行检查直接写函数。严格上说,应该对函数的输入进行检查。
需要记住的第二点,负数不是质数。同样的,1和0都不是,因此,要对这些数字做检测。另外,2是唯一的既是偶数又是质数的数字。没有必要用一个循环来验证4,6,8。再者,如果一个数字不能被2整除,它同样也不能被4,6,8等整除,因此你的循环需要跳过这些数字。可以采取其他一些更明智的优化手段,我这里采用的是适用于大多数情况的。例如,如果一个数字不能被5整除,它也不会被5的倍数整除。所以,没有必要检测10,15,20等等。如果你深入了解这个问题的解决方案,我建议你去看相关的Wikipedia介绍。
最后一点,你不需要检查比输入数字的开方还要大的数字。我感觉人们会遗漏掉这一点,并且也不会因为此而获得消极的反馈。但是,展示出这一方面的知识会给你额外加分。
现在你具备了这个问题的背景知识,下面是总结以上所有考虑的解决方案:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
function isPrime(number) { // If your browser doesn't support the method Number.isInteger of ECMAScript 6, // you can implement your own pretty easily if (typeof number !== 'number' || !Number.isInteger(number)) { // Alternatively you can throw an error. return false; } if (number < 2) { return false; } if (number === 2) { return true; } else if (number % 2 === 0) { return false; } var squareRoot = Math.sqrt(number); for(var i = 3; i <= squareRoot; i += 2) { if (number % i === 0) { return false; } } return true;} |
结论
本文以问题和练习的形式讨论了另外几个重要的Javascript概念,这些都是前端开发者面试的重要内容。我希望你能顺利地回答这些问题,或者从这里学到一些新的东西,以便在下一次面试中有更好的表现。
[转]5个JavaScript面试题的更多相关文章
- 你应该知道的25道Javascript面试题
题目来自 25 Essential JavaScript Interview Questions.闲来无事,正好切一下. 一 What is a potential pitfall with usin ...
- 互联网中级Javascript面试题
互联网中级Javascript面试题 1.实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number.String.Object.Array.Boolean)进行值复制 ...
- 互联网公司前端初级Javascript面试题
互联网公司前端初级Javascript面试题 1.JavaScript是一门什么样的语言,它有哪些特点?(简述javascript语言的特点)JavaScript是一种基于对象(Object)和事件驱 ...
- 一道 JavaScript 面试题
有一道 JavaScript 面试题. f = function () { return true; }; g = function () { return false; }; (function() ...
- 人人网javascript面试题
JavaScript面试题要求:以下题目必须从一至四题中,选出三道题,使用原生代码实现,不可使用任何框架,第五题为选作题. 一. 在页面的固定区域内实现图片的展示 <ignore_ ...
- 【转】典型的JavaScript面试题
问题1: 作用域(Scope) (function() { "use strict"; var a = b = 5; })(); console.log(b); 控制台(conso ...
- 5个经典的JavaScript面试题
在IT界中公司对JavaScript开发者的要求还是比较高的,但是如果JavaScript开 发者的技能和经验都达到了一定的级别,那他们还是很容易跳到优秀的公司的,当然薪水就更不是问题了.但是在面试之 ...
- JavaScript面试题链接汇总
最新JavaScript笔试题(含答案) - 爱思资源网 前端工程师面试问题列表 - 爱思资源网 腾讯最新前端面试题记录分享 - 爱思资源网 优酷前端JS部分面试题 - 爱思资源网 百度校园招聘web ...
- (转载)7个去伪存真的JavaScript面试题
7个去伪存真的JavaScript面试题 上周,我发表了<C#程序员的7个面试问题>.这次我要说的是如何淘汰那些滥竽充数的JavaScript程序员. 作者:小峰来源:码农网|2015-0 ...
- 一个javascript面试题
javascript面试题代码: <script type="text/javascript"> function fun(x,y){ console.log(&quo ...
随机推荐
- WeakSelf宏的进化(转载)
我们都知道在防止如block的循环引用时,会使用__weak关键字做如下定义: __weak typeof(self) weakSelf = self; 后来,为了方便,不用每次都要写这样一句固定代码 ...
- mac安装lavaral
1,安装composer # brew install josegonzalez/php/composer
- CodeForces 659F Polycarp and Hay
并查集,$dfs$. 从大的数字往里加,每加一个数字合并一下连通块,判断连通块内数字个数是否够,以及k能不能被当前加入的数字整除.然后$dfs$一下构造答案. #pragma comment(link ...
- CodeForces 712D Memory and Scores
$dp$,前缀和. 记$dp[i][j]$表示$i$轮结束之后,两人差值为$j$的方案数. 转移很容易想到,但是转移的复杂度是$O(2*k)$的,需要优化,观察一下可以发现可以用过前缀和来优化. 我把 ...
- openstack私有云布署实践【11.2 计算nova - compute节点配置(办公网环境)】
这里我只使用compute1节点配置为示例,其它节点的配置基本是一样的,只是声明的管理IP不同而已 计算节点 # yum install openstack-nova-compute sysfsu ...
- Laravel默认使用utf8_unicode_ci 即使数据库是utf8_general_ci
这样做的后果是,不方便和utf8_general_ci字符串字段进行JOIN查询ON.
- python 数据清洗之数据合并、转换、过滤、排序
前面我们用pandas做了一些基本的操作,接下来进一步了解数据的操作, 数据清洗一直是数据分析中极为重要的一个环节. 数据合并 在pandas中可以通过merge对数据进行合并操作. import n ...
- GNU/Linux超级本ZaReason Ultralap 440体验
老早就在网上看到有关ZaReason公司推出了业界首款Linux超级本Ultralap 430的新闻.通过网上搜索,我了解到ZaReason是一家专门制作与销售预装Linux台式机.笔记本.超级本.平 ...
- Oracle新建实例后,修改sys和system密码。
sqlplus/nolog connect sys as sysdba alert user sys identified by pwd;
- Docker 网络 Flannel
flannel 安装 sudo yum install kernel-headers golang gccyum install flannel flannel 配置 在etcd中设置变量 etcdc ...