上一篇:作?域鏈
下一篇:getter 與 setter
主要內容:
- 閉包的基本概念
- 閉包的基本形式
- 閉包與內存
?般?認為閉包是?個神秘??晦澀的內容. 實際上并?如此. 接下來詳細說
明閉包的概念和閉包的?般的形式, 同時討論閉包的有點和缺點.
閉包的基本概念
所謂的閉包, 簡單說就是允許低級?鏈訪問?級?鏈的數據的結構.
在 "作?域鏈" ?節中介紹過, ?級?鏈可以直接訪問低級?鏈的數據, 但是反過來?法訪問:
var num1 = 123;
function foo() {
var num2 = 456;
console.log("1 級?鏈允許訪問 0 級?鏈 " + num1);
}
foo();
try {
console.log(num2);
} catch (e) {
console.log("0 級?鏈?法訪問 1 級?鏈的數據");
}
但是如果允許訪問這個數據, 那就構成閉包結構.
閉包的通俗含義
閉包, 從字?意義上來解釋, 就是包裹起來的, 封閉起來的結構. 在
JavaScript
中, 函數就是?個封閉的結構. 在函數中定義的數據, 在外?是訪問不到的.
(function () {
var num = 123,
obj = {},
arr = [],
isTrue = false,
str = "abc",
foo = function() {};
})();
在函數外?是絕對?法訪問??定義的數據的. 因此它就構成?個封閉的結構. 但是沒有任何作?, 因此在
JavaScript
中需要將其對外開放?些接?, 以便使?這些數據. 這就是要求函數返回?個數據, 好么函數要么對象.
閉包的基本結構
要在函數外訪問函數內的數據, 最簡單的就是返回?個函數:
function foo() {
var num = 123;
return function() {
return num;
}
}
當函數返回?個函數的時候, 返回的函數允許返回?個數據. 那么在函數外就可以訪問函數內的數據了. 但是僅僅是訪問這個數據, 有時需要對其進?修改.因此既要求獲得數據, 也要求可以修改數據. 因此就需要兩個函數, 那可以返回?個對象:
function foo() {
var num = 123;
return {
get_Num: function() {
return num;
},
set_Num: function(value) {
num = value;
}
}
}
var o = foo();
console.log(o.get_Num()); // => 123
o.set_Num(456);
console.log(o.get_Num()); // => 456
?結?下閉包的這個結構:
- ?先有?個函數, 在函數中定義數據
- 同時返回?個函數, 允許訪問函數內部的數據
- 調?函數, 返回允許訪問內部數據的函數
- 利?返回的函數, 允許在外界訪問函數內定義的數據
閉包的基本案例
有了閉包, 可以做到事情就變得?常多了. 下?通過?個案例來說明閉包的使?
使?閉包模擬私有變量
// v3 使??法, v5 可以直接使? getter
var person = function(name, age, gender) {
return {
get name() {
return name;
},
get age() {
return age;
},
get gender() {
return gender;
}
}
};
var obj = person("jk", 19, "male");
console.log(obj.name);
console.log(obj.age);
console.log(obj.gender);
使?閉包模擬塊級作?域
var sum = 0;
(function () {
for (var i = 0; i <= 100; i++) {
sum += i;
}
})();
console.log(sum);
使?閉包創建唯?標識符
var uniqueInteger = (function () {
var count = 0;
return function() {
return count++;
};
})();
閉包與內存
使?閉包可以?常?便的組織代碼, 將不需要對外公開的代碼都封裝起來, 保護起來. 使得代碼更加緊湊, 維護更加?便. 但是使?閉包, 保存了私有數據,容易造成內存的泄露.
為了更加?便的解釋這個問題, ?先討論?下
JavaScript
中內存的管理.
內存管理
JavaScript
具有垃圾收集的功能. 也就是說當執?環境會負責管理代碼的執?過程使?的內存, 包括內存的分配與釋放. 在傳統的程序設計中, 例如C
,C++
,需要?動的管理內存, 申請, 釋放都需要?動的處理. 因此容易出現問題. 在JavaScript
中不需要這么?煩, 所有的事情都由JavaScript
引擎去完成.
常?的內存管理?式有兩種: 標記式, 引?計數式.
使?標記式內存管理, 運?時在內存中會標記所有的不再使?的數據, 進?加以回收. 如今?部分瀏覽器所采?的是標記式內存管理. 只是進?內存回收的時間不同?已.
使?引?計數式內存管理, 運?時會給每?個對象加上編號, 凡是有變量指向該對象, 引?計數就
+1
, 凡是減少?個引?, 計數就-1
. 那么當引?計數為0
的時候, 回收內存. 但是?旦出現循環引?, 就容易造成內存泄露.
在
JavaScript
中不需要??考慮內存維護的問題, 所有的內存維護都可以由JavaScript
引擎去處理. 但是為了更好的提升性能, 建議在不使?數據的時候,將其設置為 null
上一篇:作?域鏈
下一篇:getter 與 setter
?結
- 閉包的基本概念
- 閉包的實現?式
- 閉包案例