1、一道關(guān)于閉包和定時(shí)器的面試題
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
}
console.log(new Date, i);
很多人可能快速的掃過(guò)代碼,覺(jué)得答案是0,1,2,3,4,5
其實(shí)并不然,仔細(xì)看下代碼會(huì)發(fā)現(xiàn),循環(huán)過(guò)程中,幾乎同時(shí)設(shè)置了5個(gè)定時(shí)器,這些定時(shí)器都會(huì)在1
s后觸發(fā),所以答案應(yīng)該是立即輸出一個(gè)5,1s后輸出5個(gè)5
如果遇見(jiàn)這種題,面試官一般會(huì)追問(wèn)了,怎么輸出5 - >0,1,2,3,4,基本大家都會(huì)想到,閉包
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)的面試官可能會(huì)繼續(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í)器,設(shè)置為5 秒
console.log(new Date, i);
}, 1000 * i);
雖然這樣確實(shí)可以達(dá)到要求,但并不完美
熟悉ES的可能很快就會(huì)想到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);
});