關(guān)鍵詞:閉包(closure)
概念:
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),對于js,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。
在了解閉包之前,首先我們了解一下作用域鏈(scope chain)
,每次定義一個函數(shù),都會產(chǎn)生一個作用域鏈。當(dāng)JavaScript尋找變量varible時(這個過程稱為變量解析),總會優(yōu)先在當(dāng)前作用域鏈的第一個對象中查找屬性varible ,如果找到,則直接使用這個屬性;否則,繼續(xù)查找下一個對象的是否存在這個屬性;這個過程會持續(xù)直至找到這個屬性或者最終未找到引發(fā)錯誤為止,下面看例子:
var s = 11
function outer(){
var a = 22;
function inner(){
var b = 33;
console.log(a);
}
console.log(s);
// console.log(b); // undefined 報(bào)錯
return inner;
}
outer(); // 11
var sss = outer(); //11
sss(); //22
這就是作用域鏈的訪問關(guān)系,內(nèi)部可以訪問外部,外部不能訪問內(nèi)部;
閉包的優(yōu)點(diǎn)
- 不產(chǎn)生全局變量,不會對全局造成污染;
- 可以讓變量永駐內(nèi)存,不會被內(nèi)存回收機(jī)制回收
- 一些高級應(yīng)用方法要靠閉包實(shí)現(xiàn)
var sss = (function(){
var a = 1;
function aaa(){
a++;
console.log(a);
}
function bbb(){
a++;
console.log(a);
}
function ccc(){
a++;
console.log(a);
}
return {
a:aaa,
b:bbb,
c:ccc
}
})();
//sss(); // 報(bào)錯
sss.a(); //2
sss.b(); //3
sss.c(); //4
以上的例子每次被引用一次,a的值都會累加一次。
通過這種方式,我們定義了一個局部變量能夠被多個函數(shù)引用,且不產(chǎn)生全局污染,這樣我們就形成了一個閉包。
閉包的寫法
//第1種寫法
function Circle(r) {
this.r = r;
}
Circle.PI = 3.14159;
Circle.prototype.area = function() {
return Circle.PI * this.r * this.r;
};
var c = new Circle(3.0); // 變量c訪問了circle的內(nèi)部函數(shù)
alert(c.area());
// 這種寫法沒什么特別的,只是給函數(shù)添加一些屬性。
//第2種寫法
var Circle = function() {
var obj = new Object();
obj.PI = 3.14159;
obj.area = function( r ) {
return this.PI * r * r;
};
return obj;
};
var c = new Circle();
alert( c.area( 1.0 ) );
// 這種寫法是聲明一個變量,將一個函數(shù)當(dāng)作值賦給變量。
//第3種寫法
var Circle = new Object();
Circle.PI = 3.14159;
Circle.Area = function( r ) {
return this.PI * r * r;
};
alert( Circle.Area( 1.0 ) );
// 這種方法最好理解,就是new 一個對象,然后給對象添加屬性和方法。
//第4種寫法
var Circle={
"PI":3.14159,
"area":function(r){
return this.PI * r * r;
}
};
alert( Circle.area(1.0) );
// 這種方法使用較多,也最為方便。var obj = {}就是聲明一個空的對象。
閉包的函數(shù)傳參
有時候我們想給事件添加一些參數(shù),就可以用閉包的方式實(shí)現(xiàn)
function move(speed) {
return function() {
box.style.left = box.offsetLeft + speed + "px";
}
}
btn1.onclick = move(125);
btn2.onclick = move(-125);
閉包的缺點(diǎn)
由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
* btn1.onclick =null;