js篇(随时更新)

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);
});

你可能感兴趣的:(js篇(随时更新))