2013-07-30 109 views
1

像這樣:爲什麼認爲使用匿名函數而不是函數引用作爲參數更好?

addEventHandler(document.getElementById('btnAdd'), "click", function() 
    { addNewItem(); }, false); 

代替:

addEventHandler(document.getElementById('btnAdd'), "click", addNewItem, false); 

我知道這是涉及到JavaScript解釋器(一個或多個)工作一多一點。但是如何?

+0

在你的例子中,使用匿名函數沒有意義。 – Jivings

+1

你從哪裏聽說你的第一個例子是更好的練習? – Ian

+0

當需要將參數傳遞給來自當前作用域的'addNewItem'時,第一個參數很有用。你的第二個例子顯然不能這樣做。但我不會稱之爲「更好」的做法。 **不使用匿名函數的另一個原因是當它處於循環內部並且您以這種方式調用'addEventHandler'時。你可以在每次迭代時創建一個新函數,當你可以很容易地引用'addNewItem',它會創建一次 – Ian

回答

4

使用命名功能允許:

  • 短,更具可讀性,行
  • 描述性的名稱
  • 容易別處功能

傳遞匿名函數,什麼都不做,除了重用調用單個其他函數(如您的示例)只是膨脹 - 內聯函數表達式的冗長性,同時仍具有命名函數,它是兩個世界中最糟糕的。

+0

我在回答中指出了一些好處。 –

+0

+1,但有一種情況需要anon函數:當明確需要* not *來傳遞'event'參數(或類似的)時。 – Bergi

2

使用命名功能包括:

  • 更多的代碼
  • 全球空間的污染
  • 不太可讀的代碼,因爲它不是很明顯,函數在其他地方沒有
  • 使用

因此,如果您不重用函數,最好使用匿名函數而不是創建命名函數。

但是,如果你的代碼恰好是你展示的代碼,那麼匿名函數根本就沒有意義。什麼是第二碼相當於匿名相當於是

addEventHandler(document.getElementById('btnAdd'), "click", function() { 
    // addNewItem implementation 
}, false); 

而且如果你已經有一個名爲功能,例如,因爲你重用它,那麼就不要使用匿名函數來包裝它。

+4

它不一定會污染全局命名空間......聲明可能在關閉中 – Jivings

+1

@Jivings好,然後你做一個外部l匿名函數只是爲了避免使用匿名函數作爲回調...如果函數沒有被重用,那真的沒有意義。 –

+0

@dystroy - 編號函數聲明是有作用域的。您不必使用函數表達式來對其進行限定,因此它不會是匿名的。 – Quentin

1

我打算給我的意見而不是聲稱這是最佳做法。我曾經總是將引用作爲參數傳遞給命名函數,而我絕不會傳遞小包裝匿名函數,因爲我可以避免它。但是,我已經擺脫了這個標準。現在,當我不懷疑我的函數的簽名有太多迭代時,我傳入了對命名函數的引用,並且當我懷疑函數的簽名會迭代時,我會傳入包裝函數的匿名函數。

我會用這個JS Fiddle來解釋我以前的標準,現行標準,以及爲什麼我放棄了舊標準。總之,我從一些錯誤中瞭解到,包裝匿名函數的傳遞可以更安全地重構,因爲您必須明確地編寫要傳遞給函數的參數。不過,這兩種模式都有它們的位置。

var btn = document.getElementById('btn'); 
var btn2 = document.getElementById('btn2'); 

//I previously tended to pass in function name references. However, I recently moved towards 
//passing in anonymous functions because I found that pattern to be a bit more refactor safe. 
//More specifically, it is more refactor safe when you suspect the signature of our function 
//will change. If you never expect the function's signature to change, then I guess you shouldn't 
//need to worry about passing in an anonymous function. 

//Because of the way addEventListener uses addNewItem, addNewItem will always receive one 
//paramter: the event object. Therefore, we are not using addNewItem correct. It expects one 
//argument that is message. Previously, we were calling addNewItem correctly when it looked like 
//addNewItemOld and expected zero arguments. Click "Add message incorrect" to see the incorrect 
//behaviour 
btn.addEventListener("click", addNewItem); 

//Now I often to wrap my function calls in anonymous functions because I know exactly what arguments 
//I'm passing into my function. In this case I am explicitely not passing in a message. Now, we are 
//using the addNewItem function correctly 
btn2.addEventListener("click", function(e) { addNewItem(); }); 

//This function has been refactored. It used to look like addNewItemOld. The way 
//this function's signature has been refactored is particularly interesting. It now 
//has an optional paramter called message. 
function addNewItem(message) { 
    var span =document.createTextNode(message || "Now nodes have a default message"), 
     workspace = document.getElementById("workspace"); 
    workspace.appendChild(span); 
} 

function addNewItemOld() { 
    var span =document.createTextNode("Every node has the same message"), 
     workspace = document.getElementById("workspace"); 
    workspace.appendChild(span); 
} 
相關問題