2016-07-29 134 views
0

我一直在尋找一些JavaScript代碼來創建一個計算器應用程序。這很簡單,但是讓我困惑的是當函數返回一個函數時。函數返回一個函數(JavaScript)的

與下面的代碼,我明白了計算器的每個按鈕需要一個事件偵聽器來使用「點擊」,在其功能取決於被點擊了哪個按鈕調用。 addValue(i)函數在單擊按鈕時將按鈕值添加到結果字段。下面的函數有一個返回函數的函數。沒有函數調用,結果返回「789 + 456-123/0. = x」

有些人可以解釋爲什麼addValue(i)函數需要返回函數才能使此函數正常工作。要做到這一點

for (var i=0; i<buttons.length; i++) { 
    if(buttons[i] === "="){ 
     buttons[i].addEventListener("click", calculate(i)); 
    } else { 
     buttons[i].addEventListener("click", addValue(i)); 
    } 
} 

function addValue(i) { 
    return function() { 
     if(buttons[i].innerHTML === "÷") { 
      result.innerHTML += "/"; 
     } else if (buttons[i] === "x") { 
      result.innerHTML += "*"; 
     } else { 
      result.innerHTML += buttons[i].innerHTML; 
     } 
    } 
}; 
+4

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

回答

-1

方式一:

for (var i=0; i<buttons.length; i++) { 
    (function(i) { 
     if(buttons[i] === "="){ 
      buttons[i].addEventListener("click", function() { calculate(i) }); 
     } else { 
      buttons[i].addEventListener("click", function() { addValue(i) }); 
     } 
    })(i); 
} 

你可以閱讀更多關於JavaScript的關閉here

所以從我收集下面馬蒂(和重新閱讀您的問題),你想知道爲什麼你需要返回一個函數(或類似)。 addEventListener需要一個在發生點擊事件時被調用的函數。因爲你沒有直接調用函數(也就是運行它),所以你沒有任何發言權來傳遞參數。在這種情況下,唯一傳遞的參數是一個事件對象,包含有關點擊發生的位置,綁定到的元素等的信息。您必須將其包含在另一個函數中才能傳遞值i到您必須運行的最終功能。 (我已經在上面顯示了另一個例子)。

+2

請解釋downvote嗎? – FrankerZ

+0

你的「這裏有這個代碼」的例子是OP的第一個地方嘗試和理解的另一個排列...... – Marty

+0

我給了他代碼,並給了他一個可以進一步解釋閉包的鏈接。這是一個什麼問題? – FrankerZ

1

在本例中,我假設該網頁是一個計算器,類似於:

|---------------| 
|    | 
|---------------| 
| 1 | 2 | 3 | * | 
|---|---|---|---| 
| 4 | 5 | 6 |/| 
|---|---|---|---| 
| 7 | 8 | 9 | = | 
|---------------| 

在這種情況下,按鈕buttons[i]是計算器按鈕中的一個; | 1 || 5 |等按鈕的實際數量是它的指數,所以buttons[2]| 2 |buttons[7]| 7 |,等我猜其他值,像buttons[0]buttons[10],是經營者的按鈕(| = || * ||/|)。

現在,當對這些按鈕中的一個,在按鈕上的字符,這是該按鈕的innerHtml,被添加到用戶點擊計算器的result(通過將其添加到結果的innerHTML),這僅僅是一個顯示操作。所以,如果我點擊| 3 |,然後| * |,然後| 5 |,計算器看起來像

|---------------| 
|   3*5 | 
|---------------| 
| 1 | 2 | 3 | * | 
|---|---|---|---| 
| 4 | 5 | 6 |/| 
|---|---|---|---| 
| 7 | 8 | 9 | = | 
|---------------| 

下面是其中addEventListener用武之地。當你調用element.addEventListener("click", func),只要單擊elementfunc將被調用。因此,要單擊時按鈕添加到結果,你可以這樣做:

buttons[i].addEventListener("click", addButtonValueToResult); 

其中addButtonValueToResult是按鈕的值添加到結果的功能。

的問題是,不同的按鈕有不同的價值觀,所以像這樣的功能不會爲所有這些工作。因此,addButtonValueToResult不能是一個簡單的功能;每個按鈕都需要自己的功能。這樣的一個解決方案是溝for循環,只是這樣做:

buttons[1].addEventListener("click", add1ToResult); 
buttons[2].addEventListener("click", add2ToResult); 
buttons[1].addEventListener("click", add3ToResult); 
... 

再有這樣的功能:

function add1ToResult() { 
    result.innerHTML += "1" 
} 

但是這需要花費很多不必要的工作,因爲你需要添加功能對於每個數字按鈕(| 1 || 9 |)以及操作員按鈕(| = |,|/|| * |),它們只是將innerHtml s添加到結果中。而且,按鈕的索引已經分配給一個變量i,整個按鈕可以用該索引與buttons[i]引用。難道你不能讓程序自動爲每個按鈕創建一個函數:當給定按鈕的索引i時,獲取按鈕(通過buttons[i])並將該按鈕的值添加到結果中?

那麼這正是這個程序所做的:addValue(i)不只是添加按鈕的內部值本身;它返回另一個功能,也有一些特殊按鈕的測試用例,添加按鈕的內部值。看看這個代碼:

function addValue(i) { 
    return function() { 
     if(buttons[i].innerHTML === "÷") { 
      result.innerHTML += "/"; 
     } else if (buttons[i] === "x") { 
      result.innerHTML += "*"; 
     } else { 
      result.innerHTML += buttons[i].innerHTML; 
     } 
    } 
}; 

說你叫addValue(3);這將返回一個函數,將result中的數字3添加到結果中。如果您撥打addValue(9);這將返回一個函數,將9添加到結果中,位於result。您可以調用函數addValue返回,並通過(addValue(digit)())實際向結果添加數字。但addEventListener不會計算評估結果;它需要一個函數,它將在稍後點擊該按鈕時調用。