1. 下面代码的输出是什么?
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
这道题考的是变量提升,在预编译中,函数执行之前,会将变量和形参提升到函数最顶端(放到AO对象,并赋值为undefined),然后才开始执行代码。所以输出name的时候,name的值为undefined;输入age的时候会发生引用错误(ReferenceError),因为当js引擎向作用域中查找age变量的时候无法找到(这个知识点可以阅读《你不知道的JavaScript -- 上卷第一章》),那为什么找不到呢?因为age是使用ES6的let命令声明的,,而let命令的特点就是防止变量提升,所以在声明age变量之前去访问它的时候是会发生引用错误的。最后该题目的答案是:undefined 和 ReferenceError 。
2. 下面代码的输出是什么?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
这道题考的是作用域多一点,其次也能考察到对于for循环的理解。先来思考第一个for循环,使用的是var命令来声明变量i,那么变量i就是全局的了,当 i = 0; i = 1; i = 2;的时候都会执行for循环里面的代码块,当 i = 3的时候代码块里面的代码不会被再次执行。而代码块中是一个定时器,也就是说setTimeout里面的console.log(i)并不会立即执行,当它开始执行的时候,i 的值已经是3了,因为前面说到了 i 是全局的变量,所以第一个for循环会输出3个3。
再来看第二个for循环,使用的是let命令声明的 i ,它是这个for循环里边的局部变量。当 i = 0的时候,代码块中 i 的值也被“锁死”跟局部变量 i 绑定了,当 i 为1和2的时候原理也是一样。当 i 等于3的时候代码块不再执行,此时开始输出 i 的值依次顺序为:0、1、2
所以第一个for循环输出的值为:3、3、3;第二个for循环输出的值为:0、1、2。
3. 下面代码的输出是什么?
const shape = {
radius: 10,
diameter() {
return this.radius * 2;
},
perimeter: () => 2 * Math.PI * this.radius
};
shape.diameter();
shape.perimeter();
该题目考的是ES6中箭头函数的this指向,先来看shape.diameter(),这个肯定是返回20,因为this指向的是当前对象shape。perimeter这个方法中,使用的是箭头函数,所以this指向的是调用该方法的作用域,而该题中的调用位置是在全局作用域中,全局作用域的this指向是window。window中并没有radius属性,所以this.radius返回的是undefined;当表达式进行运算时,首先执行 2 * Math.PI 这里返回 6.28,然后6.28 * undefined,这里无法得到一个有效的数字,所以会返回NaN。该题的答案为:20和NaN。