概念篇
閉包介紹
閉包是js開發常的技巧,那麼什麼是閉包呢?
來自百度百科
閉包就是能夠讀取其他函數內部變量的函數。
例如在javascript中,只有函數內部的子函數才能讀取局部變量,所以閉包可以理解成“定義在一個函數內部的函數“。
在本質上,閉包是將函數內部和函數外部連接起來的橋樑
來自菜鳥教程
閉包是一種保護私有變量的機制,在函數執行時形成私有的作用域,保護裏面的私有變量不受外界干擾。
直觀的說就是形成一個不銷燬的棧環境。
簡而言之:閉包就是一個函數。
稍微具體點:閉包就是能夠讀取另一個函數內部變量的函數
閉包特點:
- 讓外部訪問函數內部變量成爲可能
- 函數變量會常駐在內存中,不會隨着函數的結束而自動銷燬。
- 可以避免使用全局變量,防止全局變量污染
- 會造成內存泄漏(有一塊內存空間被長期佔用而不被釋放)
應用篇
結論:閉包找到的是同一地址中父級函數中對應變量最終的值
咱先以菜鳥教程的計數器來談一哈
例一:
var add = (function () {
var counter = 0;
return function () {
return counter += 1;
}
})();
add(); //1
add(); //2
add(); //3
變量 add 指定了函數自我調用的返回值。自我調用函數只執行一次。設置計數器爲 0。並返回函數表達式。add變量可以作爲一個函數使用。它可以訪問函數上一層作用域的計數器。計數器受匿名函數的作用域保護,只能通過 add 方法修改。
例二:
function funA() {
var a = 10; // funA的活動對象之中;
return function(){ //匿名函數的活動對象;
alert(a);
}
}
var b = funA();
b(); //10
例三:
function funA() {
var a = 0;
function funB(){
a++;
console.log(a);
}
return funB;
}
var b = funA();
b(); //1
b(); //2
b(); //3
var b2 = funA();
b2(); //1
b2(); //2
例四:
var i = 0;
function funA(){
function funB(){
i++;
console.log(i);
}
return funB;
}
var b1 = funA();
var b2 = funA();
b1(); //1
b2(); //2
b1(); //3
b2(); //4
例五:
function fn(){
var a = 5;
return function(){
return ++a;
}
}
console.log(fn()()); //6
console.log(fn()()); //6
例六:
(function() {
var m = 0;
function getM() { return m; }
function seta(val) { m = val; }
window.g = getM;
window.f = seta;
})();
f(100);
console.log(g()); //100 閉包找到的是同一地址中父級函數中對應變量最終的值
例七:
var add = function(x) {
var sum = x;
var tmp = function(x) {
sum = sum + x;
return tmp;
}
tmp.toString = function() {
return sum;
}
return tmp;
}
alert(add(1)(2)(3)); //6
例八:
var lis = document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].onclick = function(){
console.log(i);
};
})(i); //事件處理函數中閉包的寫法
}
例九:
function m1(){
var x = 1;
return function(){
console.log(++x);
}
}
m1()(); //2
m1()(); //2
var m2 = m1();
m2(); //2
m2(); //3
例十:
var fn=(function(){
var i=10;
function fn(){
console.log(++i);
}
return fn;
})()
fn(); //11
fn(); //12
面試篇
var x = 2
var y = {
x:3,
z:(function(x){
this.x *= x;
x += 2
return function(n) {
this.x *= n;
x += 3;
console.log(x)
}
})(x)
}
var m = y.z
m(4) //7
y.z(6) //10
console.log(x,y.x) //16 18