题目
已知数组["a","b","c","d","e"]
,编写代码,每过 1 秒打印一下数组中的值。
答案
ES5
var arr = ["a", "b", "c", "d", "e"];
for (var i = 0; i < arr.length; i++) {
(function(j) {
var item = arr[j];
setTimeout(function() {
console.log(item);
}, 1000 * (i + 1));
})(i);
}
复制代码
ES6
利用 ES6 中 let 块级作用域的特性。
var arr = ["a", "b", "c", "d", "e"];
for (let i = 0; i < arr.length; i++) {
const item = arr[i]; // let | const
setTimeout(() => {
console.log(item);
}, 1000 * (i + 1));
}
复制代码
思考
看题目很容易意识到这是在考块级作用域,考点主要是 ES5 里没有块级作用域,但可以用闭包来模拟块级作用域。
一个普通的循环
for (var i = 0; i < 5; i++) {
console.log(i);
}
// 0 1 2 3 4
复制代码
加上 setTimeout
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
// 5 5 5 5 5
复制代码
setTimeout
属于注册事件,绑定的事件是当前事件队列(同步事件)执行完毕后再执行,因此等到执行console.log
的时候,i
已经变成 5 了。
再来一题
思考以下代码的打印结果。
var test = function() {
var arr = [];
for (var i = 0; i < 3; i++) {
arr[i] = function() {
return i * i;
};
}
return arr;
};
var a = test();
a[1](); // 9
a[2](); // 9
复制代码
执行 test()
的结果是一个数组,里面每一个元素都是function
,在实际调用的时候,i
的值已经是 3 了,因此结果都是 9。