什麼是JavaScript閉包?
剛開始知道這個詞,就誤以爲是自動執行的匿名函數塊。
比如說+function(){}();
然而並不是,那麼請看下面的例子:
function init() {
var name = "initial";
function displayName() {//displayName() is the inner function, a closure
alert(name);
}
displayName();
}
init();
displayname()是閉包嗎?函數內部訪問函數成員局部屬性的方法?
This is an example of lexical scoping: in JavaScript, the scope of a variable is defined by its location within the source code (it is apparent lexically) and nested functions have access to variables declared in their outer scope
這是一個詞法域的例子:Javascript中,變量的作用域由他所在的代碼區域(明顯的詞法上的),和可以訪問外部作用域的嵌套方法組成。
閉包Closure
再看這個例子:
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
What’s different — and interesting — is that the displayName() inner function was returned from the outer function before being executed.
不同並且有趣的地方是:內部方法displayName在函數外面被return出來,還是在執行之前。
那麼可以大膽的說:myFunc就是一個閉包。
A closure is a special kind of object that combines two things: a function, and the environment in which that function was created.
閉包就是一個包含了兩個東西的特殊對象:一個方法和創建這個方法的環境。
再看看一個例子 :
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
顯然add5和add10各自都有各自的環境,所持有的變量是不同的。
看一個閉包引起的錯誤,比較難理解透。
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
}
}
setupHelp();
如果有三個輸入框,那麼每個框點擊都會導致#help的內容變成Your age (you must be over 16)。
原因是:賦值給document.getElementById(item.id).onfocus
的function是個閉包函數:,這裏循環創建了三個閉包,但是他們共享了同一個外部作用域,也就是setupHelp,那麼自然循環結束的時候,onfocus 裏面就是指向了數據的最後一個元素。
這些話並不太容易讓人相信。
我debug跟蹤了一下:
循環走完的時候,onfocus function(){}裏面 item 的id已經是’age’,help是
‘Your age (you must be over 16)’
三個input對象都是onfocus綁定了同一個閉包(等同於同一個,環境裏變量和函數行爲都一樣)。
閉包性能
通常一個函數執行完畢之後它內部的局部變量就已經不能再訪問了。
而閉包需要維持他所被創建時的作用域環境,過分使用閉包對速度上的性能和內部的消耗是有影響的。沒必要的時候不要使用閉包。
本文引用自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures