1、一道關(guān)于閉包和定時器的面試題
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
其實并不然,仔細看下代碼會發(fā)現(xiàn),循環(huán)過程中,幾乎同時設(shè)置了5個定時器,這些定時器都會在1
s后觸發(fā),所以答案應(yīng)該是立即輸出一個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);
當(dāng)然,還有另外的解決方法,我們只要每次拿到循環(huán)體內(nè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);
變態(tài)的面試官可能會繼續(xù)刁難,那么輸出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() { // 額外增加定時器,設(shè)置為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);
});