一個普通的for迴圈裡面log一下 i
// 正常寫一個for迴圈輸出i
for (var i = 0; i < 5; i++) {
console.log(i);
}
console.log(i);
複製程式碼
假設你是一個面試者,你說說這幾行程式碼會輸出什麼?,你的內心活動會不會是“這特麼不就是一個迴圈嗎?面試官既然這麼問老子(他還笑肯定不是好東西,肯定有陷阱),好好想一下,這好像和我看的那個閉包的題很像啊,這面試官是不是沒寫完啊?怎麼辦。”
如果稍微改動一些尼,輸出結果又是什麼?
for迴圈中有一個定時器
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(new Date, i);
}1000 * i);
}
console.log(new Date, i);
複製程式碼
稍微加了點料(setTimeout)後,是不是看到這道題就舒服了,會不會想“’這不是老子背的最多的閉包問題麼,想一哈,setTimeout是會延遲執行的所以外面的log會先執行,i是用var宣告的,所以會變數提升,for迴圈裡i最後執行完i++,i變成了5,沒錯了,老子這題得分了。
使用閉包
// 閉包
for (var i = 0; i < 5; i++) {
~function (j) {
setTimeout(function () {
console.log(new Date, j);
}, 1000 * j);
}(i);
}
複製程式碼
順著上一個程式想“是不是還可以昇華一下,我還能執行出來0 1 2 3 4
真實實作
var roles = ['角色1', '角色2', '角色3'];
var arrayTest = [];
for (var i = 0; i < roles.length; i++) {
!function (i) {
$.get('https://www.baidu.com', { role: roles[i] }, function (res) {
console.log(i);
arrayTest[i] = i + roles[i] + res;
})
}(i);
}
複製程式碼
如果你登入一個後臺系統,這個賬號下有不同角色(角色不固定,後期可能增加),傳不同角色進行ajax請求得到相應渲染頁面的資料,但是這個介面只接收一個角色引數, 那我們應該怎麼按我 們想要的順序獲取資料然後渲染頁面?
使用ES6
const tasks = [];
for (var i = 0; i < 5; i++) {
((j) => {
tasks.push(new Promise((resolve) => {
setTimeout(() => {
console.log(new Date, j);
resolve();
}, 1000 * j); // 定時器的超時時間逐步增加
}));
})(i);
}
Promise.all(tasks).then(() => {
setTimeout(() => {
console.log(new Date, i);
}, 1000);
});
複製程式碼
當你前面所有問題都順利的回答完了,你想沒想過可能還有20%的人可以回答到你這種程度,怎麼能變現的比他們牛逼一點尼?你可以考慮使用一下promise
setTimeout 和 promise 的優先順序
setTimeout(function () {
console.log(1)
}, 0);
new Promise(function executor(resolve) {
console.log(2);
for (var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(3);
}).then(function () {
console.log(4);
});
console.log(5);
複製程式碼
這道題應該考察我 JavaScript 的執行機制的,讓我理一下思路。
首先先碰到一個 setTimeout,於是會先設定一個定時,在定時結束後將傳遞這個函式放到任務佇列裡面,因此開始肯定不會輸出 1 。
然後是一個 Promise,裡面的函式是直接執行的,因此應該直接輸出 2 3 。
然後,Promise 的 then 應當會放到當前 tick 的最後,但是還是在當前 tick 中。
因此,應當先輸出 5,然後再輸出 4 。
最後在到下一個 tick,就是 1 。
2 3 5 4 1
使用ES7
const sleep = (timeountMS) => new Promise((resolve) => {
setTimeout(resolve, timeountMS);
});
(async () => { // 宣告即執行的 async 函式表示式
for (var i = 0; i < 5; i++) {
await sleep(1000);
console.log(new Date, i);
}
await sleep(1000);
console.log(new Date, i);
})();
複製程式碼
要是想給面試官留一個關注新技術的更牛逼印象,那就用es7說一下吧。
關於我們
視訊課程線上觀看-----傳送門
視訊課程網盤地址-----傳送門 提取碼: ifv9
冰山社團官網地址-----傳送門
如果觀看視訊或文件後,你覺得有些收穫,願意加入冰山社團與我們一同成長,請進入我們的官網,點選冰山社團,加入我們~