1、一道关于闭包和定时器的面试题
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
}
console.log(new Date, i);
很多人可能快速的扫过代码,觉得答案是0,1,2,3,4,5
其实并不然,仔细看下代码会发现,循环过程中,几乎同时设置了5个定时器,这些定时器都会在1
s后触发,所以答案应该是立即输出一个5,1s后输出5个5
如果遇见这种题,面试官一般会追问了,怎么输出5 - >0,1,2,3,4,基本大家都会想到,闭包
for (var i = 0; i < 5; i++) {
(function(j) { // j = i
setTimeout(function() {
console.log(new Date, j);
}, 1000);
})(i);
}
console.log(new Date, i);
当然,还有另外的解决方法,我们只要每次拿到循环体内部的i值就可以
var output = function (i) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
};
for (var i = 0; i < 5; i++) {
output(i);
}
console.log(new Date, i);
变态的面试官可能会继续刁难,那么输出0 -> 1 -> 2 -> 3 -> 4 -> 5喃?
for (var i = 0; i < 5; i++) {
(function(j) { // j = i
setTimeout(function() {
console.log(new Date, j);
}, 1000*j);
})(i);
}
setTimeout(function() { // 额外增加定时器,设置为5 秒
console.log(new Date, i);
}, 1000 * i);
虽然这样确实可以达到要求,但并不完美
熟悉ES的可能很快就会想到Promise
const tasks = []; // 这里存放所有异步的 Promise
const output = (i) => new Promise((resolve) => {
setTimeout(() => {
console.log(new Date, i);
resolve();
}, 1000 * i);
});
// 生成全部的异步操作
for (var i = 0; i < 5; i++) {
tasks.push(output(i));
}
// 异步操作完成之后,输出i
Promise.all(tasks).then(() => {
setTimeout(() => {
console.log(new Date, i);
}, 1000);
});