今天知乎看到一個專欄岭皂,欄主就面試中的閉包問題吐槽了下現(xiàn)今一些前端從業(yè)者郊霎。
廢話不說,進(jìn)入正題爷绘。书劝。。
// 請問輸出什么
for (var i = 0; i < 10; ++i) {
setTimeout(function () {console.log(i)}, 0);
}
以上這段代碼輸出什么土至?第二問购对,如果想讓這段代碼輸出0123456789,應(yīng)該怎么修改陶因?
這是個閉包的問題骡苞,我也就這個問題再度復(fù)習(xí)了一下閉包。
解決方案很多:
方案1:
for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e)
}, 1000)
})(i)
}
方案2:
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000) //注意這邊callback傳入一個自執(zhí)行函數(shù)(閉包)坑赡,頭一回這么見覺得很神奇
}
方案3:es6語法var改成let烙如,當(dāng)然如果面試遇到相同的問題,面試官一般會排除用es6語法毅否。
另一個閉包問題:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = function() {
console.log( i);
};
}
for (var j = 0; j < 3; j++) {
funcs[j](); // 3 3 3
}
解決方案如下:
var funcs = [];
function createfunc(i) {
return function() { console.log(i); };
}
for (var i = 0; i < 3; i++) {
funcs[i] = createfunc(i);
}
for (var j = 0; j < 3; j++) {
funcs[j](); //0 1 2
}
總結(jié)
對于for循環(huán)等無塊級作用域的語句表達(dá)式亚铁,在循環(huán)中的函數(shù)引用了所在執(zhí)行環(huán)境中的同一個變量i,i在循環(huán)中可變螟加,我們需要的是給循環(huán)中的函數(shù)傳入不同的參數(shù)并且這個參數(shù)在其所在執(zhí)行環(huán)境中是不可變的徘溢。
看了驚鴻三世的JavaScript之閉包與高階函數(shù),得出了以下結(jié)論:
理解并利用閉包需要知道閉包的作用:
- 封裝變量
- 模仿塊級作用域
封裝變量
var mult = function() {
var a = 1;
for (var i = 0, len = arguments.length; i < len; i++) {
a = a * arguments[i];
}
return a;
}
alert(mult(1,2,3,4));
模仿塊級作用域
(function() {
//塊級作用域
})()