1 以下代码执行后,控制台中的输入内容为?
for (let i = 0; i < 3; i++) {setTimeout(() => {console.log(i);
});
}
for (var j = 0; j < 3; j++) {setTimeout(() => {console.log(j);
});
}
2 以下代码执行后,控制台中的输入内容为?
if (!("a" in window)) {var a = 1;}
if (!("b" in window)) {let b = 1;}
console.log(window);
console.log(a);
console.log(b);
3 以下代码执行后,控制台中的输入内容为?
function fn() {
var i = 0;
return function () {console.log(i++);
};
}
var f1 = fn();
var f2 = fn();
f1();
f1();
f2();
1、答案:0 1 2 3 3 3
解析:var 申明的变量没有块级作用域,在 for 循环中应用 var 申明迭代变量 j 会导致所有 setTimeout 中应用的 j 指向同一个变量,而 setTimeout 属于宏工作,执行的机会在失常工作队列之后,即此处 for 循环退出之后开始执行,此时迭代变量保留的是导致循环退出的值 3,因而所有 setTimeout 的回调函数都会输入 3
而 let 申明迭代变量时,JS 引擎会为每个迭代循环申明一个新的迭代变量,每个 setTimeout 援用的都是不同的变量实例,所以最初输入 0 1 2
2、答案:undefined 报错:Uncaught ReferenceError: b is not defined
var 申明的变量没有块级作用域,并且存在变量晋升,因而该题代码等价于:
var a;
if (!("a" in window)) {a = 1;}
此时 a 为全局变量,而由 var 申明的全局变量会成为 window 的属性,因而 if 语句块中的代码不会执行,所以 console.log(a)
输入 undefined
而 let 申明的变量存在块级作用域的概念,所以 let b 不会成为全局变量,即便其成为全局变量,也不会成为 window 的属性,因为 let 申明的全局变量不会成为 window 的属性,所以在 console.log(b)
所在的作用域(全局)中,未声明变量 b,因而会报错:Uncaught ReferenceError: b is not defined
3、答案:0 1 0
var 申明的变量不存在块级作用域,然而存在部分作用域,此题中变量 i 的作用域为 fn 函数作用域
每次调用 fn
都会造成一个闭包,不同闭包之间是独立的不会相互烦扰
闭包会将 i 的值保留下来,屡次调用 fn() 返回的函数会批改 i 的值
所以最终会输入:0 1 0
公众号【明天也要写 bug】