2016-12-05 40 views
0

我正在閱讀Mozilla開發人員網站上有關閉包的解釋,我正在努力一點。請從Mozilla網站上查看以下代碼。我有點理解它是如何工作的,但我認爲我的意見下面的代碼也應該工作。如果點擊18和20,爲什麼它不起作用?JavaScript - Closures

/* mozilla dev code */ 
function makeSizer(size) { 
    return function() { 
     document.body.style.fontSize = size + 'px'; 
    }; 
} 

var size12 = makeSizer(12); 
var size14 = makeSizer(14); 
var size16 = makeSizer(16); 

document.getElementById('size-12').onclick = size12; 
document.getElementById('size-14').onclick = size14; 
document.getElementById('size-16').onclick = size16; 
/* end of mozilla dev example */ 
/* my code starts */ 
/* see - no inner function below */ 

function makeS(size) { 
     document.body.style.fontSize = size + 'px' 
} 
/* Let's see if that works */ 

var size18 = makeS(18); 
document.getElementById('size-18').onclick = size18; 



/* What about that? */ 

document.getElementById('size-20').onclick = makeS(20); 

爲什麼

CodePen: http://codepen.io/wasteland/pen/qqoooW

+0

[JavaScript關閉如何工作?]的可能重複(http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – s3raph86

回答

6

makeS(18)立即調用函數並更改大小。在這種情況下分配給onclick事件的實際上是undefined,因爲這是調用時函數返回的內容,因爲它沒有明確的返回。

function makeS(size) { 
 
     document.body.style.fontSize = size + 'px' 
 
} 
 

 
console.log("font size before calling makeS:", document.body.style.fontSize); //it's actually an empty string, hence why it doesn't show up in the output 
 

 
var size18 = makeS(18); 
 

 
console.log("font size after calling makeS:", document.body.style.fontSize); 
 

 
console.log("what is size18?", typeof size18);

相比之下,makeSizer(18)創建一個新的功能調用的時候,是否會改變大小。

function makeSizer(size) { 
 
    return function() { 
 
     document.body.style.fontSize = size + 'px'; 
 
    }; 
 
} 
 

 
console.log("font size before calling makeSizer:", document.body.style.fontSize); //it's actually an empty string, hence why it doesn't show up in the output 
 

 
var size18Function = makeSizer(18); 
 

 
console.log("font size after calling makeSizer:", document.body.style.fontSize); //it's still an empty string 
 

 
console.log("what is size18Function?", typeof size18Function); 
 

 
//let's call it now 
 
size18Function(); 
 

 
console.log("font size after calling size18Function:", document.body.style.fontSize); //it's now changed

0

18只你打電話讓ONCLICK。它沒有任何返回size18,siz18此處將不確定的,如果你想讓它通過clousre變化使(工作),返回類似於makeSizer

檢查這個片段的方法

function makeSizer(size) { 
 
    return function() { 
 
    document.body.style.fontSize = size + 'px'; 
 
    }; 
 
} 
 

 
var size12 = makeSizer(12); 
 
var size14 = makeSizer(14); 
 
var size16 = makeSizer(16); 
 

 
document.getElementById('size-12').onclick = size12; 
 
document.getElementById('size-14').onclick = size14; 
 
document.getElementById('size-16').onclick = size16; 
 

 

 
function makeS(size) { 
 
    return function() { 
 
    document.body.style.fontSize = size + 'px'; 
 
    } 
 
} 
 

 
/* Let's see if that works */ 
 

 
var size18 = makeS(18); 
 
document.getElementById('size-18').onclick = size18; 
 

 

 
/* What about that? */ 
 

 
document.getElementById('size-20').onclick = makeS(20);
body { 
 
    font-family: Helvetica, Arial, sans-serif; 
 
    font-size: 12px; 
 
} 
 
h1 { 
 
    font-size: 1.5em; 
 
} 
 
h2 { 
 
    font-size: 1.2em; 
 
}
<h1>How closures work</h1> 
 
<a href="#" id="size-12">12</a> 
 
<a href="#" id="size-14">14</a> 
 
<a href="#" id="size-16">16</a> 
 

 
<div> 
 
    <a href="#" id="size-18">18</a> 
 
    <a href="#" id="size-20">20</a> 
 
</div>

希望這有助於

4

閉包是在定義時由函數的範圍鏈的「記憶」變量的事實。由於函數的參數僅僅是執行過程中的局部變量,這樣:

function makeSizer(size) { 
    return function() { 
     document.body.style.fontSize = size + 'px'; 
    }; 
} 

是等效於:

function makeSizer() { 
    var size = 1; // or some other value 
    return function() { 
     document.body.style.fontSize = size + 'px'; 
    }; 
} 

在上述情況下,匿名功能,這是返回值,將「記住'值爲size變量,並在每次調用時使用它。

應將MakeSizer視爲「工廠」功能,爲局部變量size提供不同的值。

如果不在'工廠'功能中使用函數定義語句,就無法實現這種'記憶'。

0

閉包是指保留訪問它所聲明的詞法範圍內的變量的函數的概念,即使它被傳遞並在整個程序的不同位置和範圍中調用。

咦?

這是什麼意思呢?考慮下面的代碼

function functionFactory() { 
    var x = 1; 
    return function() { 
     return ++x; 
    }; 
} 

var first = functionFactory(); 
var second = functionFactory(); 

console.log(first()); // outputs 1 
console.log(first()); // outputs 2 
console.log(first()); // outputs 3 

console.log(second()); // outputs 1 

每次functionFactory被調用時,它聲明一個私有變量x,然後返回變異變量的匿名函數。我們可以在輸出中看到,該返回函數first的每個後續調用返回一個不同的值。

雖然我們打電話second,它返回1.爲什麼?因爲它是由functionFactory單獨調用而創建的,所以它自己引用了自己的關閉,其編號爲x

爲什麼我在意?

因爲這是超級有用的。在編程語言(如JavaScript,但也包括其他函數式語言)中,我們可以使用閉包來封裝私有變量。

因此您的實際問題...

爲什麼你的代碼是不工作的原因,是因爲onclick希望你的函數分配給它 - 而不是你分配你的makeS函數的輸出,這是voidmakeSizer正在返回一個函數,該函數建立一個關於任何數值作爲參數傳遞給它的閉包,然後將其分配給每個元素的變量onclick

希望這可以讓你的事情變得更加清晰。