什么是閉包? 有什么作用
可以先看下一段代碼
function outerFn() {
console.log("Outer function");
function innerFn() {
console.log("Inner function");
}
return innerFn;
}
var fnRef = outerFn();
fnRef();
其中innerFn()為內(nèi)部函數(shù),在outerFn()外無(wú)法直接調(diào)用。但是可以讓outerFn()返回innerFn。這樣可以在outerFn()外間接調(diào)用函數(shù)innerFn()。
- 即使離開(kāi)函數(shù)作用域的情況下仍然能夠通過(guò)引用調(diào)用內(nèi)部函數(shù)的事實(shí),意味著只要存在調(diào)用內(nèi)部函數(shù)的可能,JavaScript就需要保留被引用的函數(shù)。而且JavaScript運(yùn)行時(shí)需要跟蹤引用這個(gè)內(nèi)部函數(shù)的所有變量,直到最后一個(gè)變量廢棄,JavaScript的垃圾收集器才能釋放相應(yīng)的內(nèi)存空間)。
- 閉包是指有權(quán)限訪問(wèn)另一個(gè)函數(shù)作用域的變量的函數(shù)??衫斫鉃閯?chuàng)建閉包的常見(jiàn)方式就是在一個(gè)函數(shù)內(nèi)創(chuàng)建另一個(gè)函數(shù)。
setTimeout 0 有什么作用
- setTimeout是一個(gè)延時(shí)函數(shù),當(dāng)設(shè)定延遲的時(shí)間為0時(shí),會(huì)使setTimeout內(nèi)部的函數(shù)在所有要執(zhí)行的js語(yǔ)句執(zhí)行完成之后再執(zhí)行。
代碼題目
下面的代碼輸出多少?修改代碼讓fnArri 輸出 i。使用兩種以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); //
方法1.1 利用函數(shù)參數(shù)傳遞使得num=i
var fnArr = [];
for (var i = 0; i < 10; i ++) {
(function(num){
fnArr[i] = function(){
return num;
};
})(i)
}
console.log( fnArr[3]() ); //
方法1.2 直接用命名定義 var num =1;在此函數(shù)內(nèi)未找到i,返回上一級(jí)尋找i
var fnArr = [];
for (var i = 0; i < 10; i ++) {
(function(){
var num = i;
fnArr[i] = function(){
return num;
};
})()
}
console.log( fnArr[3]() ); //
方法2.1直接用命名定義 var num =1;在此函數(shù)內(nèi)未找到i,返回上一級(jí)尋找i
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function(){
var num =i;
return function(){
return num;
}
})();
}
console.log( fnArr[3]() ); //
方法2.2利用函數(shù)參數(shù)傳遞使得num=i
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function(num){
return function(){
return num;
}
})(i);
}
console.log( fnArr[3]() ); //
四種方法的核心:
1、創(chuàng)建函數(shù)(立即執(zhí)行函數(shù))
2、使 num =i ;(使用var num =i;或者用函數(shù)參數(shù)傳遞)
3、return num;
使用閉包封裝一個(gè)汽車對(duì)象,可以通過(guò)如下方式獲取汽車狀態(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
代碼如下
function getCar(){
var i =0;
function setSpeed(k){
i = k;
}
function accelerate(){
i +=10;
}
function decelerate(){
i -=10;
}
function getSpeed(){
return i;
}
function getStatus(){
if(i>0){
return 'running'
}else{
return 'stop'
}
}
return {
setSpeed: setSpeed,
accelerate: accelerate,
decelerate: decelerate,
getSpeed: getSpeed,
getStatus: getStatus
}
}
var Car = getCar();
寫(xiě)一個(gè)函數(shù)使用setTimeout模擬setInterval的功能
function interval(func,time){
return setTimeout(function(){
func();
interval(func,time);
},time);
}
注意要點(diǎn):需要將func()寫(xiě)在setTimeout()內(nèi)部

寫(xiě)一個(gè)函數(shù),計(jì)算setTimeout平均[備注:新加]最小時(shí)間粒度
function mini(){
var i = 0;
var start = Date.now();
var clock = setTimeout(function(){
i++;
if(i === 1000){
clearTimeout(clock);
var end = Date.now();
console.log((end-start)/i);
}
clock =setTimeout(arguments.callee,0)
},0)
}
mini()
下面這段代碼輸出結(jié)果是? 為什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
var a ;
console.log(a);
a = 3;
console.log(a);
//1,3,2
//setTimeout是一個(gè)延時(shí)函數(shù),當(dāng)設(shè)定延遲的時(shí)間為0時(shí),會(huì)使setTimeout內(nèi)部的函數(shù)在所有要執(zhí)行的js語(yǔ)句執(zhí)行完成之后再執(zhí)行。
下面這段代碼輸出結(jié)果是? 為什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
到while(flag){}卡主,因?yàn)閟etTimeout導(dǎo)致flag =false處于最后,當(dāng)執(zhí)行到while(flag){}時(shí),由于flag為true導(dǎo)致停在此代碼處。
下面這段代碼輸出?如何輸出delayer: 0, delayer:1...(使用閉包來(lái)實(shí)現(xiàn))
for(var i=0;i<5;i++){
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
console.log(i);
}
代碼如下
for(var i=0;i<5;i++){
(function(num){
setTimeout(function(){
console.log('delayer:' + num );
}, 0);
})(i)
console.log(i);
}