https://developer.mozilla.org...
closure is the combination of a function and the lexical environment within which that function was declared.
閉包是一個函數和其內部公開變量的環境的集合.
簡單而言, 閉包 = 函數 + 環境閉包
function init() { var name = 'Mozilla'; // name is a local variable created by init function displayName() { // displayName() is the inner function, a closure alert(name); // use variable declared in the parent function } displayName(); } init(); because inner functions have access to the variables of outer functions, displayName() can access the variable name declared in the parent function, init().
var data = [ {'key':0}, {'key':1}, {'key':2} ]; function showKey() { for(var i=0;i<data.length;i++) { setTimeout(function(){ //console.log(i); //發現i輸出了3次3 //console.log(this); // 發現 this 指向的是 Window data[i].key = data[i].key + 10; console.log(data[i].key) }, 1000); } } showKey();
上面這個例子能夠正確輸出 10 11 12 嗎?
答案是:並不能,而且還會報語法錯誤....函數
因此須要再定義一個執行函數this
var data = [ {'key':0}, {'key':1}, {'key':2} ]; function showKey() { var f1 = function(n){ data[i].key = data[i].key + 10; console.log(data[i].key) } for(var i=0;i<data.length;i++) { setTimeout(f1(i), 1000); } } showKey(); // 獲得預期的 10 11 12
function makeAdder(x) { return function(y) { return function(z) { return x + y + z; } }; } console.log(makeAdder(1)(2)(3)); // 6 // function factory it creates functions which can add a specific value to their argument var add5 = makeAdder(5); console.log(add5(1)(2)); // 8 console.log(add5(4)(5)); // 14
var counter = (function() { // private variable var privateCounter = 0; // private function function changeBy(val) { privateCounter += val; } return { changeValue: function(val) { changeBy(val); }, value: function() { return privateCounter; } }; })(); console.log(counter.value()); // logs 0 // 實現了內部屬性的獲取 counter.changeValue(2);// 實現了內部的changeBy()方法 counter.changeValue(10); console.log(counter.value()); // logs 12 counter.changeValue(-5); console.log(counter.value()); // logs 7
var makeCounter = function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } } }; var counter1 = makeCounter(); var counter2 = makeCounter(); alert(counter1.value()); /* Alerts 0 */ counter1.increment(); counter1.increment(); alert(counter1.value()); /* Alerts 2 */ counter1.decrement(); alert(counter1.value()); /* Alerts 1 */ alert(counter2.value()); /* Alerts 0 */