剛學過的閉包,分享一下閉包的理解
1.什么是閉包?
閉包就是一個函數(shù),也可以說閉包是一個引用關(guān)系,可以理解為一個作用域可以訪問另一個函數(shù)的局部變量。
代碼:
function fn() {
var num = 10;
function fun() {
console.log(num);
}
fun();
}
fn();
函數(shù)調(diào)用后,運行結(jié)果為10;
可以理解為 fun函數(shù)內(nèi)部作用域訪問到了fn函數(shù)內(nèi)部的私有變量num,fn函數(shù)調(diào)用后,訪問到了內(nèi)部的局部變量。
這就引出了閉包產(chǎn)生的條件。
2.閉包的產(chǎn)生條件?
a.函數(shù)的嵌套;
b.內(nèi)部函數(shù) 引用外部函數(shù)的局部變量;
c.調(diào)用外部函數(shù);
3.閉包的作用
a. 延長外部函數(shù)變量對象的生命周期(也可以認為延伸了變量的作用范圍);
b. 讓函數(shù)外部可以操作(讀寫)到函數(shù)內(nèi)部的數(shù)據(jù)(變量/函數(shù)),通過閉包間接的操作;
c.注意: 瀏覽器為了性能后期將外部函數(shù)中不被內(nèi)部函數(shù)使用的變量清除了;
一段代碼當中 究竟存在幾套閉包機制 取決于外部函數(shù)調(diào)用了幾次
代碼塊一
function fn() {
var a = 0;
function fn1() {
a ;
console.log(a)
}
return fn1;
}
var f = fn();
f();
f();
f();
解析:因為fn函數(shù)只調(diào)用了一次,創(chuàng)建了一次執(zhí)行環(huán)境,后續(xù)的執(zhí)行全在這一次創(chuàng)建的執(zhí)行環(huán)境里,所以a ,也在原有的基礎上增加。
**所以輸出結(jié)果為 1,2,3;**閉包機制只有一套
代碼塊二
function fn() {
var a = 0;
function fn1() {
a ;
console.log(a)
}
return fn1;
}
fn();
fn();
fn();
解析:fn函數(shù)被調(diào)用了三次,每調(diào)用一次,就 創(chuàng)建一次新的執(zhí)行環(huán)境,執(zhí)行完成好進行銷毀,所以每次調(diào)用a就從0開始 ,所以輸出結(jié)果為1,1,1;閉包機制有三套
3.常見的閉包
a. 將函數(shù)作為另一個函數(shù)的返回值;
b. 將函數(shù)作為實參傳遞給另一個函數(shù)調(diào)用;
c. 使用閉包實現(xiàn)私有方法操作獨立的私有屬性;
看如下代碼
functionc fn(){
var num =10;
function fun(){
console.log(num);
}
return fun;
}
var f = fn();
console.log(f);
console.log(f());
將函數(shù)作為另一個函數(shù)的返回值;
解析
var f =fn();
fn();//fn 運行 返回值是fun函數(shù)
var f =function fun(){
console.log(num);
}
所以console.log(f)打印出來的是 10
因為 fun函數(shù)沒有返回值,先運行一遍fun函數(shù),再打印出fun函數(shù)的返回值;所以console.log(f());打印出來的值是 10,undefined
4.閉包的生命周期
1. 產(chǎn)生: 在嵌套內(nèi)部函數(shù)定義完時就產(chǎn)生了(不是在調(diào)用),外部函數(shù)調(diào)用的時候;
2. 死亡: 在嵌套的內(nèi)部函數(shù)成為垃圾對象時;
5.閉包的缺點和解決(內(nèi)存泄漏和內(nèi)存溢出)
內(nèi)存泄漏 : 內(nèi)存無法釋放;
內(nèi)存溢出 : 內(nèi)存被撐爆;
f = null; 解決方式;讓閉包機制清除,必須刪除外部函數(shù)調(diào)用的時候生成的(定義的那個對應內(nèi)部函數(shù));
6.閉包面試題
代碼段1
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
console.log(object.getNameFunc()());
解析
//解析
var f = object.getNameFunc();
var f = function() {
return this.name;
}
f();
function() {
return this.name;
}(); //相當于立即執(zhí)行函數(shù) this指向的是window
此題沒有用到閉包
所以輸出結(jié)果為 The Window;
代碼段2
var name2 = "The Window";
var object2 = {
name2: "My Object",
getNameFunc: function () {
var that = this;
return function () {
return that.name2;
};
}
};
console.log(object2.getNameFunc()());
解析
典型的一個作用域可以訪問另一個函數(shù)的局部變量。是閉包
var that =this;
這個this指的調(diào)用者object2對象,所以that也是object2對象,所以that.name2指的是object2的name屬性。輸出結(jié)果為 My Object;
聯(lián)系客服