問題
什么是閉包? 有什么作用
閉包可以用來讀取函數(shù)內(nèi)部的變量鳄乏。
function f1() {
var n = 999;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); //999
由于作用域鏈表跷车,外部是無法讀取到函數(shù)內(nèi)部的變量的。所以如果想要得到函數(shù)內(nèi)部的變量橱野,可以在函數(shù)體內(nèi)部再定義一個函數(shù)朽缴,這個用這個函數(shù)返回所需要的變量。
function create_counter(initial) {
var x = initial || 0;
return { inc: function () {
x += 1;
return x;
}
}}
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13
- 上面例子中水援,c1,c2引用的外部函數(shù)的x密强,是獨立的兩個值,封閉的包裝蜗元。
- 閉包可以理解為是攜帶狀態(tài)的函數(shù)或渤,并且它的狀態(tài)可以完全對外隱藏起來。
setTimeout 0 有什么作用
setTimeout(f, 0) ; 將第二個參數(shù)設為 0奕扣,作用是讓 f 在現(xiàn)有的任務(腳本的同步任務和“消息隊列”指定的任務)一結束就立刻執(zhí)行薪鹦。也就是說,setTimeout(f, 0)的作用是惯豆,盡可能早地執(zhí)行指定的任務池磁,而并不是會立刻就執(zhí)行這個任務。
- 可以用于調(diào)整事件的發(fā)生順序楷兽;
- 將一些消耗性能的任務地熄,分成小塊放到setTimeout(f, 0)中,可以減輕性能壓力芯杀。
代碼題
下面的代碼輸出多少端考?修改代碼讓fnArr[i]()
輸出 i。使用兩種以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); //10
這段代碼輸出10揭厚。上段循環(huán)中却特,將一個函數(shù),依次寫進一個數(shù)組中棋弥,而這個函數(shù)不是立即執(zhí)行的核偿,通過fnArr[]()
調(diào)用,才進行執(zhí)行顽染。所以當循環(huán)結束后漾岳,此時i的數(shù)值已經(jīng)變化為10,當調(diào)用fnArr[3]()
,實際上執(zhí)行的是return i ;
粉寞,而此時的 i 就是 10尼荆。
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function (n){
return function (){
return n;
};
})(i);
}
console.log( fnArr[3]() ); //3
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function fn(){
return fn.id;
};
fnArr[i].id = i;
}
console.log( fnArr[5]() ); //5
使用閉包封裝一個汽車對象,可以通過如下方式獲取汽車狀態(tài)
function car(){
var speed = 0;
return {
setSpeed:function(val){
speed = val;
return speed;
},
getSpeed:function(){
console.log(speed);
return speed;
},
accelerate:function(){
speed += 10;
},
decelerate:function(){
speed -= 10;
if (speed < 0){
speed = 0;
}
},
getStatus:function(){
if(speed!==0){
console.log('running');
return 'running';
}
else {
console.log('stoped');
return 'stoped';
}
}
};
}
var Car = car();
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; //undefined;
寫一個函數(shù)使用setTimeout模擬setInterval的功能
var i = 0;
function interval(){
setTimeout(function(){
console.log(i++);
interval();
},1000);
}
interval();
寫一個函數(shù)唧垦,計算setTimeout最小時間粒度
function getMini(){
var i = 0;
var start = Date.now();
var timer = setTimeout(function(){
i++;
if(i === 1000){
clearTimeout(timer);
var end = Date.now();
console.log((end-start)/i);
}
timer = setTimeout(arguments.callee,0);
},0);
}
getMini();//4.112//4.117
下面這段代碼輸出結果是? 為什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);//3執(zhí)行
}, 0);
var a ;
console.log(a); //1執(zhí)行
a = 3;
console.log(a);//2執(zhí)行
//1 3 2
-
setTimeout(func,0)
會將任務在下一個Event Loop之前執(zhí)行捅儒,所以這里的function被移到了最后進行執(zhí)行。
下面這段代碼輸出結果是? 為什么?
var flag = true;
setTimeout(function(){
flag = false;
},0);//理論上不會執(zhí)行
while(flag){}
console.log(flag);//理論上不會執(zhí)行
- setTimeout將function移到下一個Event Loop之前執(zhí)行,但是while將這個阻斷了巧还,陷入了無限循環(huán)鞭莽。所以flag不能被賦值成false。這也說明程序的運行是單線程的麸祷。
下面這段代碼輸出澎怒?如何輸出delayer: 0, delayer:1...(使用閉包來實現(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);
}
本教程版權歸 張宇 及 饑人谷 所有,轉載請標明出處阶牍。