1. 什么是閉包?
這個問題會放到后面回答. 這里先提出大家在編程的時候常見的幾個其他問題
- 全局變量都會自動直接放到全局對象上, 這樣會導致全局對象受到變量污染, 大家有解決方案嗎?
答: 可以對耦合比較強的代碼片段放到 "匿名自執(zhí)行函數(shù)" 里 - 如果在處理的時候, 想針對有些函數(shù)處理的中間結(jié)果做緩存,有沒有好的解決思路?
答: 可以封裝一個對象,然后全局保持這個對象的引用, 處理中間結(jié)果放到對象內(nèi)部 - 可以讓 JavaScript 實現(xiàn)面向?qū)ο缶幊虇?
答: 在創(chuàng)建的對象里, 對象的屬性是無法被外部訪問的, 而是由對象提供的外部可訪問的方法.
閉包 :
在 JavaScript 中, 函數(shù)是對象, 對象是屬性的集合. 當我們在函數(shù)內(nèi)部創(chuàng)建一個內(nèi)部函數(shù), 然后在函數(shù)內(nèi)部可以保持當前函數(shù)執(zhí)行的運行狀態(tài), 然后把內(nèi)部函數(shù)傳給外部用來調(diào)用, 這就是閉包概念.
2. 閉包的使用場景
2.1 : 創(chuàng)建匿名自執(zhí)行函數(shù)
示例會為 Global 對象進行屬性和方法的初始化, 初始化過程中創(chuàng)建的變量或者方法對應(yīng)的臨時變量都會隨著 匿名自執(zhí)行函數(shù)(閉包) 執(zhí)行結(jié)束而銷毀
var Global = {};
(function(global){
var qa = navigator.userAgent;
if(typeof qa != 'undefined'){
global.qa = qa;
}
var print = function(x){
console.log("the print result :" + x);
}
global.print = print;
})(Global)
Global.print(Global.qa);
執(zhí)行結(jié)果:
執(zhí)行場景
2.2 實現(xiàn)面向?qū)ο缶幊?/h4>
在函數(shù) Student 中, score 只是其一個局部變量, 由于Student執(zhí)行結(jié)果被持有, 所以 函數(shù)Student執(zhí)行時的執(zhí)行狀態(tài)被保留下來了, 只能通過 getScore 去獲取 score 而且也可以通過 setScore 去修改 score, 但不能直接通過 student 對象做任何操作
var Student = function(){
this.score = 11;
return {
getScore: function(){
return score;
},
setScore: function(newScore){
score = newScore;
}
}
};
var student = Student();
console.log(student.score);
console.log(student.getScore());
student.setScore(66)
console.log(student.getScore());
var studentObject = new Student();
//仍然是 undefined, 因為執(zhí)行構(gòu)造函數(shù),也是根據(jù)構(gòu)造函數(shù)的返回去覆蓋實際對象
console.log(studentObject.score);
執(zhí)行結(jié)果:
2.3 緩存
function Student(){
this.id = -1;
this.name = undefined;
}
var SearchStudentData = (function(){
var cache = new Array;
var size = 0;
return {
searchStudent : function(id){
var item = cache[id];
if(typeof item == 'undefined'){
item = new Student;
item.id = id;
item.name = "student_" + (size++);
cache[item.id] = item;
}
return item;
}
}
})();
console.log(SearchStudentData.searchStudent(1).name);
console.log(SearchStudentData.searchStudent(1).name);
執(zhí)行結(jié)果:
第二次輸出結(jié)果命中結(jié)果