问题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行以上的代码,那么准确理解和恰当使用闭包是非常重要的。控制台会输出两次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面试题解析 #### 一、ES6的新语法 ES6(ECMAScript 6)是JavaScript语言标准的一个重要版本,它引入了许多新的特性和语法改进,旨在提高开发效率和代码可读性。以下是一些重要的新特性: 1. **let ...
18.md 5个典型的JavaScript面试题(上) JavaScript 19.md 再来5个JavaScript面试题 JavaScript 20.md BAT web前端开发方向校招都考些什么? General 21.md Eleme 笔试题 General 22.md 一些JS题目的解答 ...
"JavaScript面试题集锦详解" 这篇文章涵盖了JavaScript的多个方面,包括eval函数、window和document对象、null和undefined的区别、数组的map方法、事件机制、use strict模式等。 eval函数 eval函数可以将字符串...
JavaScript常见面试题
这份“JavaScript面试题”文档旨在帮助你深入理解JavaScript的基础和高级概念,以便在面试中展现出扎实的技术功底。以下是一些关键的知识点,涵盖了标题和描述中提及的JavaScript面试重点。 1. **基本语法与数据...
JavaScript 面试题知识点总结 JavaScript 面试题是前端开发领域中常见的面试题,涵盖了 JavaScript 基础、Web 前端开发等方面的知识点。本文将对 JavaScript 面试题的知识点进行总结,包括 Object.create、...
JavaScript面试题汇总涵盖了广泛的知识点,以下是其中一些关键点的详细说明: 1. **变量声明**:在JavaScript中,可以使用var关键字声明变量。在给定的题目中,选项A `( )` 是一个无效的声明,因为没有提供任何值,...
以下是一些基于给定面试题集锦的知识点详细说明: 1. **undefined 和 null 的区别**:`undefined` 表示变量已声明但未定义,而 `null` 是一个特殊值,表示一个空或无值的引用。 2. **&& 运算符**:它执行逻辑与...
根据给定的信息,我们将深入分析并提取出与JavaScript面试题相关的知识点。 ### 一、单选题 #### 1. 以下哪条语句会产生运行错误: - **选项A**: `var obj = ();` - **解析**:在JavaScript中,括号`()`通常用于...
Java面试题、设计模式面试题、Spring面试题、MyBatis面试题、Memcached面试题、MongoDB面试题、ZooKeepe面试题、RabbitMQ面试题、HTML面试题、CSS面试题、Vue面试题、React面试题、JavaScript面试题、2021java面试题...
JavaScript面试题及答案-共60道.docx JavaScript面试题及答案-共60道.docx JavaScript面试题及答案-共60道.docx JavaScript面试题及答案-共60道.docx JavaScript面试题及答案-共60道.docx JavaScript面试题及答案-共...
JavaScript 是一种广泛应用于网页和网络应用的脚本...以上内容涵盖了JavaScript面试中常见的知识点,这些基础和进阶知识是每个前端开发者都需要掌握的。理解并熟练运用它们,对于解决实际问题和提升开发效率至关重要。
大公司javaScript经典面试题汇总
本文总结了百度前端JavaScript面试题,涵盖了多个知识点,包括左定右自适应布局、GetPosition方法、模拟fadeIn和fadeOut、call和apply的区别和应用场景、创建a标签点击弹出对应序号、Ajax的关键步骤和注意事项、页面...
JavaScript是一种广泛应用于Web开发的...以上是对这套JavaScript面试题的解析,涵盖的知识点全面,适合准备JavaScript面试的开发者进行自我检测和学习。理解并掌握这些知识点,对于提升JavaScript编程能力大有裨益。
JavaScript进阶面试题_30题.pdf_前端面试题 从这份文件中,我们可以总结出以下的知识点: 1. ECMAScript6 中的类语法糖:ECMAScript6 中引入了类语法糖,这使得有 OOP 基础的人更容易上手 JavaScript。虽然对熟悉 ...
JavaScript面试题.md