間接實(shí)現(xiàn)訪問控制:(父對象讀取不了子對象的變量,但是子對象可以讀取父對象的變量)
var foo = ( function() {
var secret = 'secret';
// “閉包”內(nèi)的函數(shù)可以訪問 secret 變量,而 secret 變量對于外部卻是隱藏的
return {
get_secret: function () {
// 通過定義的接口來訪問 secret
return secret;
},
new_secret: function ( new_secret ) {
// 通過定義的接口來修改 secret
secret = new_secret;
}
};
} () );
foo.get_secret (); // 得到 'secret'
foo.secret; // Type error,訪問不能
foo.new_secret ('a new secret'); // 通過函數(shù)接口,我們訪問并修改了 secret 變量
foo.get_secret (); // 得到 'a new secret'
閉包的作用:
閉包可以用在許多地方。它的最大用處有兩個(gè),一個(gè)是前面提到的可以 讀取/修改 函數(shù)內(nèi)部的變量,另一個(gè)就是讓這些變量的值始終保持在內(nèi)存中。
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
為什么局部變量n會一直保存在內(nèi)存中呢?原因就在于f1是f2的父函數(shù),而f2被賦給了一個(gè)全局變量,這導(dǎo)致f2始終在內(nèi)存中,而f2的存在依賴于f1,因此f1也始終在內(nèi)存中,不會在調(diào)用結(jié)束后,被垃圾回收機(jī)制(garbage collection)回收。
this在不同環(huán)境下的結(jié)果:
var object={name:'my object',getName:function(){
var that=this; // 提前賦值,避免了環(huán)境切換導(dǎo)致的變異。
return function(){return that.name;
};
}
}
console.log(object.getName()()); // my object
var object={name:'my object',getName:function(){
return function(){return this.name;
};
}
}
console.log(object.getName()()); // The window