問題
1.什么是閉包? 有什么作用
閉包(英語:Closure)肛真,又稱詞法閉包(Lexical Closure)或函數(shù)閉包(function closures)写妥,是引用了自由變量的函數(shù)媚污。這個被引用的自由變量將和這個函數(shù)一同存在断医,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。所以债蓝,有另一種說法認為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實體壳鹤。閉包在運行時可以有多個實例,不同的引用環(huán)境和相同的函數(shù)組合可以產(chǎn)生不同的實例饰迹。
在函數(shù)內(nèi)定義的變量,在其內(nèi)部返回函數(shù),返回的函數(shù)使用函數(shù)定義的變量,就會形成閉包;閉包可以減少全局變量,還可以對函數(shù)進行封裝;
下面例子形成了簡單的閉包
function f1() {
var a=10;
var b=20;
function f2() {
console.log(a);
}
f2();
}
f1();
應(yīng)用更多的形式:
function f1() {
var a=10;
var b=20;
return function f2() {
console.log(a);
}
}
var result=f1();
console.log(result());
2.setTimeout 0
有什么作用
使用setTimeout 0可以實現(xiàn)異步芳誓,可以等待當前任務(wù)完成之后,在執(zhí)行setTimeout 0里面函數(shù)的內(nèi)容啊鸭,因為javascript是單線程執(zhí)行代碼的锹淌,無法同時執(zhí)行多段代碼,所以當一個代碼執(zhí)行的時候赠制,后續(xù)的代碼必須等待赂摆,形成一個隊列,一旦當前任務(wù)執(zhí)行完畢,才從隊列中取出下面的一個任務(wù)執(zhí)行烟号,使用seTimeout 0就是利用了這個特性來延遲執(zhí)行順序绊谭。
代碼題
1.下面的代碼輸出多少?修改代碼讓fnArr[i]()
輸出 i汪拥。使用兩種以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); //
輸出10;
方法一:
var fnArr = [];
for (var i = 0; i < 10; i++) {
fnArr[i] = (function(num) {
return function() {
return num;
}
})(i);
}
console.log(fnArr[9]()); //
方法二:
function f() {
function test(x) {
return function() {
return x;
}
}
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = test(i);
}
return a;
}
var fnArr = f();
console.log(fnArr[9]()); //
2.使用閉包封裝一個汽車對象达传,可以通過如下方式獲取汽車狀態(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
var Car = (function() {
var speed = 0;
var status = 'stop';
var acceleratevalue = 10;
var deceleratevalue = -10;
function getSpeed() {
console.log(speed);
}
function setSpeed(num) {
speed = num;
console.log(speed);
}
function accelerate() {
speed += acceleratevalue;
console.log(speed);
}
function decelerate() {
speed += deceleratevalue;
console.log(speed);
}
function getStatus() {
status = speed > 0 ? 'running' : 'stop';
console.log(status);
}
return {
setSpeed: setSpeed,
getSpeed: getSpeed,
accelerate: accelerate,
decelerate: decelerate,
getStatus: getStatus
}
})();
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
3.寫一個函數(shù)使用setTimeout模擬setInterval的功能
var i=0;
function interval(){
setTimeout(function(){
console.log(i++);
interval();
},1000);
}
interval();
4.寫一個函數(shù),計算setTimeout最小時間粒度
function getMini() {
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, 2)
}, 2)
}
console.log(getMini())
5.下面這段代碼輸出結(jié)果是? 為什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
var a ;
console.log(a);
a = 3;
console.log(a);
setTimeout函數(shù)放在其他語句后面執(zhí)行,輸出1,3,2
6.下面這段代碼輸出結(jié)果是? 為什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
//無限循環(huán)沒有輸出迫筑。flag的初始值為true宪赶,而setTimeout的delay值被設(shè)為0,也就意味著里面的函數(shù)要等待其他語句全部執(zhí)行完畢才會運行脯燃。而while(flag){}因為flag為true的關(guān)系永遠不會停止逊朽,所以console.log(flag)也就永遠不會執(zhí)行。
7.下面這段代碼輸出曲伊?如何輸出delayer: 0, delayer:1...
for(var i=0;i<5;i++){
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
console.log(i);
}
輸出
0
1
2
3
4
delayer:4
delayer:4
delayer:4
delayer:4
delayer:4
輸出delayer: 0, delayer:1...
for (var i = 0; i < 5; i++) {
setTimeout(
(function(num) {
return function() {
console.log('delayer:' + num);
}
})(i), 0);
console.log(i);
}