什么是閉包? 有什么作用
可以先看下一段代碼
function outerFn() {
console.log("Outer function");
function innerFn() {
console.log("Inner function");
}
return innerFn;
}
var fnRef = outerFn();
fnRef();
其中innerFn()為內部函數,在outerFn()外無法直接調用。但是可以讓outerFn()返回innerFn。這樣可以在outerFn()外間接調用函數innerFn()。
- 即使離開函數作用域的情況下仍然能夠通過引用調用內部函數的事實,意味著只要存在調用內部函數的可能,JavaScript就需要保留被引用的函數。而且JavaScript運行時需要跟蹤引用這個內部函數的所有變量,直到最后一個變量廢棄,JavaScript的垃圾收集器才能釋放相應的內存空間)。
- 閉包是指有權限訪問另一個函數作用域的變量的函數。可理解為創建閉包的常見方式就是在一個函數內創建另一個函數。
setTimeout 0 有什么作用
- setTimeout是一個延時函數,當設定延遲的時間為0時,會使setTimeout內部的函數在所有要執行的js語句執行完成之后再執行。
代碼題目
下面的代碼輸出多少?修改代碼讓fnArri 輸出 i。使用兩種以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); //
方法1.1 利用函數參數傳遞使得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;在此函數內未找到i,返回上一級尋找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;在此函數內未找到i,返回上一級尋找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利用函數參數傳遞使得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、創建函數(立即執行函數)
2、使 num =i ;(使用var num =i;或者用函數參數傳遞)
3、return num;
使用閉包封裝一個汽車對象,可以通過如下方式獲取汽車狀態
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();
寫一個函數使用setTimeout模擬setInterval的功能
function interval(func,time){
return setTimeout(function(){
func();
interval(func,time);
},time);
}
注意要點:需要將func()寫在setTimeout()內部
寫一個函數,計算setTimeout平均[備注:新加]最小時間粒度
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()
下面這段代碼輸出結果是? 為什么?
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是一個延時函數,當設定延遲的時間為0時,會使setTimeout內部的函數在所有要執行的js語句執行完成之后再執行。
下面這段代碼輸出結果是? 為什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
到while(flag){}卡主,因為setTimeout導致flag =false處于最后,當執行到while(flag){}時,由于flag為true導致停在此代碼處。
下面這段代碼輸出?如何輸出delayer: 0, delayer:1...(使用閉包來實現)
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);
}