JavaScript函數(三)——閉包及作用域
阿新 • • 發佈:2018-07-29
閉包 n) 定義 var 成了 局部變量 val 執行函數 eid
閉包
概念
只有函數內部的子函數才能讀取局部變量,所以閉包可以理解成“定義在一個函數內部的函數“。在本質上,閉包是將函數內部和函數外部連接起來的橋梁
例子
function outer(){
var localVal = 30;
return localVal;
}
outer();//30
function outer(){
var localVal = 30;
return function() {
return localVal;
}
}
var func = outer();
func();//30
作用:比如在一個函數中嵌套一個函數,通過閉包可以讓嵌套函數訪問到包裹它的函數的局部變量。
封裝
(function(){ var _userId = 123; var _typeId = ‘item‘; var export = {}; function converter(userId){ return + userId; } export.getUserId = function(){ return converter(_userId); } export.getTypeId = function(){ return _typeId; } window.export = export; })(); export.getUserId();//123 export.getTypeId();//item export._uerId;//undefined export._typeId;//undefined export.converter;//undefined
閉包陷阱
var tasks = [];
for (var i=0; i<3; i++) {
tasks.push(function() {
console.log(‘>>> ‘ + i);
});
}
console.log(‘end for.‘);
for (var j=0; j<tasks.length; j++) {
tasks[j]();
}
輸出結果都為3。這個問題的原因在於,函數創建時並未執行,所以先打印end for.,然後才執行函數,由於函數引用了循環變量i,而i的作用域是整個函數,而不是循環,在函數執行時,i的值已經變成了3。
解決方法
再創建一個函數,將循環變量作為函數參數傳入:
var tasks = [];
for (var i=0; i<3; i++) {
var fn = function(n) {
tasks.push(function() {
console.log(‘>>> ‘ + n);
});
};
fn(i);
}
//簡化語法,直接用匿名函數的立即執行模式(function() { ... })()
var tasks = [];
for (var i=0; i<3; i++) {
(function(n) {
tasks.push(function() {
console.log(‘>>> ‘ + n);
});
})(i);
}
總結
優點:靈活方便,封裝
缺點:空間浪費,內存泄漏,性能消耗
JavaScript函數(三)——閉包及作用域