一、什么是閉包? 有什么作用
1.變量的作用域
??要理解閉包,首先必須理解JavaScript的變量作用域。變量的作用域無非就是兩種:全局變量和局部變量。在JavaScript中函數(shù)可以直接讀取外部的全局變量。
var a="你好";
function fun1(){
alert(a);
}
fun1();//輸出"你好"
另一方面在函數(shù)外部,無法讀取函數(shù)內部的變量。
function fun2(){
var a="你好";
}
alert(a);//瀏覽器提示錯誤,VM55:4 Uncaught ReferenceError: a is not defined(…)
這里有一個問題需要注意,函數(shù)內部聲明變量的時候,一定要使用var聲明,如果不使用var聲明,實際上是一個全局變量。
function fun2(){
a="你好";
}
fun2();
alert(a);//"你好"
2.如何從外部讀取局部變量
??當我們需要獲取到函數(shù)內部的變量的時候,我們就需要在函數(shù)的內部在定義一個函數(shù)。
function fun1(){
var a="你好";
function fun2(){
alert(a);//"你好"
}
return fun2();
}
fun1();
在上面的代碼中,函數(shù)fun2就被包括在函數(shù)fun1內部,這時fun1內部的所有局部變量,對fun2都是可見的。但是反過來就不行,fun2內部的局部變量,對fun1就是不可見的。這就是Javascript語言特有的"作用域鏈"結構(chain scope),子對象會一級一級地向上尋找所有父對象的變量。所以,父對象的所有變量,對子對象都是可見的,反之則不成立。
??既然fun2可以讀取fun1中的局部變量,那么只要把fun2做為返回值就可以獲取到fun1中的變量了。那么函數(shù)fun2就可以成為閉包了。
3.閉包的概念
??由于在Javascript中,只有函數(shù)內部的子函數(shù)才能讀取局部變量,因此可以把閉包簡單理解成"定義在一個函數(shù)內部的函數(shù)"。所以,在本質上,閉包就是將函數(shù)內部和函數(shù)外部連接起來的一座橋梁。
4.閉包的作用
??閉包可以用在許多地方。它的最大用處有兩個,一個是前面提到的可以讀取函數(shù)內部的變量,另一個就是讓這些變量的值始終保持在內存中。
5.使用閉包的注意事項
??由于閉包會使得函數(shù)中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
二、setTimeout 0 有什么作用
1.setTimeout() 方法用于在指定的毫秒數(shù)后調用函數(shù)或計算表達式。
2.setTimeout(f,0)的作用就是為了把f放到運行隊列的最后去執(zhí)行。也就是說,無論setTimeout(f,0)寫在哪,當之前的函數(shù)執(zhí)行完之后,f可以在最后立即執(zhí)行。

如上圖代碼所示,當1和3輸出之后,立即執(zhí)行的是2。
三、下面的代碼輸出多少?修改代碼讓fnArr [i] () 輸出 i。使用兩種以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); //
1.輸出的結果為10

??我們可以先分析一下為什么輸出的結果為10:

??如上圖所示,for循環(huán)內的函數(shù)可以寫成下面一種形式,因為return返回的是遍歷數(shù)組后的最后一個值10,所以最后的結果都是10。
2.方法一:賦值給立即執(zhí)行函數(shù),外部需要傳遞參數(shù)。

3.方法二:賦值給立即執(zhí)行函數(shù),聲明一個臨時變量存儲i的值,外部不需要傳參。

4.方法三:把它綁定在函數(shù)上,作為函數(shù)的一部分,不需要通過閉包,得到函數(shù)就能得到值。

四、使用閉包封裝一個汽車對象,可以通過如下方式獲取汽車狀態(tài)
var Car = //todo;
Car.setSpeed(30);
Car.getSpeed(); //30
Car.accelerate();
Car.getSpeed(); //40;
Car.decelerate();
Car.decelerate();
Car.getSpeed(); //20
Car.getStatus(); // 'running';
Car.decelerate();
Car.decelerate();
Car.getStatus(); //'stop';
//Car.speed; //error

五、寫一個函數(shù)使用setTimeout模擬setInterval的功能

1.setTimeout為延時性定時器,可以設置多長時間之后執(zhí)行代碼(只執(zhí)行一次)。
2.setInterval為間隔性定時器,可以設置每隔多久執(zhí)行一次代碼(執(zhí)行多次)。
六、寫一個函數(shù),計算setTimeout平均[備注:新加]最小時間粒度

七、下面這段代碼輸出結果是? 為什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
var a ;console.log(a);
a = 3;
console.log(a);

八、下面這段代碼輸出結果是? 為什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);

原因:以上代碼沒有輸出,因為setTimeout(f,0)會讓其包含的代碼在其它代碼執(zhí)行完后才能執(zhí)行;當執(zhí)行完第一行代碼后直接跳到while語句,而while語句中的判斷條件為真,將會一直執(zhí)行,進入死循環(huán),所有沒有輸出。
九、下面這段代碼輸出?如何輸出delayer: 0, delayer:1...(使用閉包來實現(xiàn))
for(var i=0;i<5;i++){
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
console.log(i);
}
1.方法一:利用函數(shù)f()嵌套,形成閉包,輸出delayer+i的值。

2.方法二:
