問(wèn)題
1.什么是閉包? 有什么作用
閉包(英語(yǔ):Closure),又稱(chēng)詞法閉包(Lexical Closure)或函數(shù)閉包(function closures),是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開(kāi)了創(chuàng)造它的環(huán)境也不例外。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。閉包在運(yùn)行時(shí)可以有多個(gè)實(shí)例,不同的引用環(huán)境和相同的函數(shù)組合可以產(chǎn)生不同的實(shí)例。
在函數(shù)內(nèi)定義的變量,在其內(nèi)部返回函數(shù),返回的函數(shù)使用函數(shù)定義的變量,就會(huì)形成閉包;閉包可以減少全局變量,還可以對(duì)函數(shù)進(jìn)行封裝;
下面例子形成了簡(jiǎn)單的閉包
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可以實(shí)現(xiàn)異步,可以等待當(dāng)前任務(wù)完成之后,在執(zhí)行setTimeout 0里面函數(shù)的內(nèi)容,因?yàn)閖avascript是單線程執(zhí)行代碼的,無(wú)法同時(shí)執(zhí)行多段代碼,所以當(dāng)一個(gè)代碼執(zhí)行的時(shí)候,后續(xù)的代碼必須等待,形成一個(gè)隊(duì)列,一旦當(dāng)前任務(wù)執(zhí)行完畢,才從隊(duì)列中取出下面的一個(gè)任務(wù)執(zhí)行,使用seTimeout 0就是利用了這個(gè)特性來(lái)延遲執(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.使用閉包封裝一個(gè)汽車(chē)對(duì)象,可以通過(guò)如下方式獲取汽車(chē)狀態(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.寫(xiě)一個(gè)函數(shù)使用setTimeout模擬setInterval的功能
var i=0;
function interval(){
setTimeout(function(){
console.log(i++);
interval();
},1000);
}
interval();
4.寫(xiě)一個(gè)函數(shù),計(jì)算setTimeout最小時(shí)間粒度
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ù)放在其他語(yǔ)句后面執(zhí)行,輸出1,3,2
6.下面這段代碼輸出結(jié)果是? 為什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
//無(wú)限循環(huán)沒(méi)有輸出。flag的初始值為true,而setTimeout的delay值被設(shè)為0,也就意味著里面的函數(shù)要等待其他語(yǔ)句全部執(zhí)行完畢才會(huì)運(yùn)行。而while(flag){}因?yàn)閒lag為true的關(guān)系永遠(yuǎn)不會(huì)停止,所以console.log(flag)也就永遠(yuǎn)不會(huì)執(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);
}