閉包
閉包的概念
- 閉包的含義就是閉合,簡單來講就是一個具備封閉功能的結構
- 閉包就是具備封閉的對外不公開的,包裹結構或空間
在 js 中的閉包
- 在 js 中函數能夠構成閉包
- 函數是一個代碼結構的封閉結構,具備包裹特性
- 根據做用域規則, 只容許函數訪問外部數據, 外部沒法訪問函數內部數據
- 因此說函數具備封閉的, 不公開的特效, 因此能夠構成閉包
閉包解決什麼問題
- 閉包不容許外界訪問
- 外界間接訪問閉包中的數據
- 函數能夠構成閉包, 解決的問題就是函數外訪問到函數內部的數據
獲得一個數據
function foo(){
var num = 123;
return num;
}
var result = foo();
console.log(result);
}
- 外部能夠訪問到函數內的數據
- 可是數據不能進行二次訪問, 若是再試訪問函數內部數據須要再次調用函數, 雖然獲得的移入是num = 123, 可是實際不是第一次函數調用的那個值
獲得一個函數, 經過函數訪問數據
- 在函數內的數據, 不能直接被函數外訪問,若是函數內再定義一個函數, 那麼函數內部數據能夠被函數外訪問
function foo(){
var num = Math.random();
function fn(){
return num;
}
return fn;
}
var f = foo();
// f 能夠直接訪問這個數據 num
var result1 = f();
var result2 = f();
// 獲得結果一致,說明屢次訪問的是同一個數據
獲得的數據能夠是對象
function foo(){
var o = {name : 'Bob'};
return function(){
return o;
}
}
var fn = foo();
var result = fn();
得到多個數據
function foo(){
var num1 = Math.random();
var num2 = Math.random();
return {
num1 : function(){
return num1;
},
num2 : function(){
return num2;
}
}
}
得到和修改這個數據
function foo(){
var num = Math.random();
return {
getNum : function(){
return num;
},
setNum : function(value){
num = value;
}
}
}
閉包的基本結構
- 經過函數: 寫一個函數, 函數內定義一個新函數, 返回新函數, 使用新函數獲得函數內的數據
- 經過對象: 寫一個函數, 函數內頂一個對象, 對象中綁定多個方法, 返回對象, 利用對象內的方法訪問函數內中的數據
閉包的基本用法
- 帶有私有訪問數據的對象
function Person(){
this.name = 'Peter';
// setName('')
}
// 私有數據指的是隻有函數內部能夠訪問的數據,或者對象內部的方法
// 簡單的例子,判斷孩子是否是老張家的
function createPerson(){
var name = '張全蛋';
return {
getName : function(){
return name;
},
setName : function(value){
// 若是value的第一個字符串是 張 ,就設置
if(value.charAt(0) === '張'){
name = value;
} esle {
//不姓 張 ,就將錯誤拋出
throw new Error('你不姓張,難道還能姓王?');
}
}
}
}
- 帶有私有數據的函數
// 不具備私有數據
var fn = function(){};
function fn(){}
// 具備私有數據
var foo = (function(){
// 私有數據
return function(){
// 能夠訪問私有數據
}
})();
閉包的基本模型
函數模型
function foo(){
// 私有數據
return function(){
// 能夠訪問上面的私有數據
}
}
對象模型
function foo(){
// 私有數據
return {
method : function(){
// 能夠訪問的私有數據
}
}
}
閉包的性能問題
- 函數的執行須要內存, 函數中定義的變量會在函數執行後自動回收
- 由於是閉包結構, 若是還有變量引用這些數據的話, 這些數據不會被回收
- 所以在使用閉包的時候,若是不使用這些數據了, 須要將函數賦值爲 null
var foo = (function(){
var num = 123;
return function(){
return num;
}
})();
// 若是不須要foo中的數據, 賦值爲 null
foo = null;