2012-08-31 32 views
16

我如何得到bar和foo平等的正面測試?如何在Javascript中測試函數的相等性

foo = function() { 
    a = 1; 
}; 

bar = function() { 
    a = 1; 
}; 

if (foo === bar) alert('baz'); 
if (foo == bar) alert('qux'); 

上述兩個條件都是錯誤的。

更新 - 按照要求,我需要測試功能的平等

我建立一個發佈/訂閱框架,需要通過回調序退訂話題的原因。

請參閱小提琴:http://jsfiddle.net/jamiefearon/hecMS/47/

+0

可能是你的意思是功能返回一個值?返回一個;失蹤? – frenchie

+2

如果你解釋爲什麼你想這樣做,它可能會幫助人們提供有用的答案和評論。 – Pointy

+0

所以你想檢查兩個函數的內容是否完全一樣?爲什麼你需要這樣做? –

回答

3

你可以測試一下,看看兩個變量是否完全相同的功能對象,你可以函數轉換爲字符串,看看他們是否真的一模一樣,但試圖確定兩個功能是否完全相同,會有點困難,或者更難。

通過縮小器運行一對函數會很有趣,因爲縮小器會進行大量的靜態分析。

+2

不難,但實際上不可能。 – duri

+2

@duri我在這裏瞭解到,有些事情是「不可能的」是一種羞辱的好方法:-)然而,我總體上同意你的看法,因爲對動態語言如JavaScript的完全靜態分析是不可能。 – Pointy

+3

那麼,2個函數是否等價的問題與數學相關,而不是編程,但您可能會感興趣http://stackoverflow.com/questions/1132051/is-finding-the-equivalence-of-two-functions-不確定 – duri

0

基本上,這是不可能的。沒有辦法在javascript中測試功能相等。您可以得到的最接近的結果是將它們的代碼作爲字符串進行比較以獲得相等。

+0

這顯然是不正確的 –

1

看起來好像你需要這個功能,可能會更好地重構你的程序。像這樣的東西可以工作:

function baz(myInt) { return 3 + myInt; } 
function asd(a) { return 3 + a; } 

var foo = baz; 
foo(1); //returns 4 

var bar = baz; 
bar(3); //returns 6 

foo === bar; //true 

bar = asd; 
bar(3); //returns 6 

foo === bar; //false 
20

你可以檢查兩個函數的內容是否正是一樣通過比較它們調用toString的結果

var foo = function() { 
    a = 1; 
}; 

var bar = function() { 
    a = 1; 
}; 

alert(foo.toString() == bar.toString());​ 

這將,但是,失敗如果只有一個字符是不同的。另一方面,檢查兩個功能是否是相同的事情,幾乎是不可能的。

+0

你是對的。完美的工作...... – Basith

+25

但這也完全沒用。 –

+4

絕對不是!這對於lodash去抖功能是必不可少的。 – morels

13

問題是功能上存在不同的平等概念。

  • 參考平等。函數存儲在內存中的某個地方,並從某個地址開始。對於兩個函數名稱(實際上是地址內部),引用相等會給你true如果兩個名字都指向相同的地址。這是一個問題,當你分配一個bar = foo。 JavaScript中使用引用相等。
  • 在另一個答案中提出的源代碼平等。如果你改變函數體中的任何字符,它將不起作用。此外,toSource目前(截至2014年)僅適用於Firefox,因爲它不是W3C的標準版本。
  • 源代碼的句法均等性。可以使用抽象語法樹抵制空間和註釋中的修改。可以使用lambda微積分中定義的α等價(即函數的等價性,其中變量一致地重命名),但是如果它們以相同的方式工作則函數相等時也可以使用。有a theorem指出沒有算法來檢查函數的擴展等式,所以它肯定不是你正在搜索的那個算法。然而,在一些更高級的語言比JS有
  • 內涵平等(你要麼證明函數是手工等於或程序無法通過編譯)和
  • 觀測平等(this one is too advanced to explain)。

所以,照顧你認爲平等是什麼。

+4

如果你可以爲每一個添加一個例子,那麼它會使這個很好的答案! –

0

簡單的方法:如果你實現你的subscribe API在每次調用時都返回一個唯一的ID,那麼它就像使用該ID調用unsubscribe API一樣簡單。在簡單的情況下,你可以使用一個簡單的數組來存儲所有的訂閱者,但是這種方法你必須存儲。一個ID可以是一個簡單的計數器,您可以通過每次訂閱呼叫來遞增。

{ID:用戶」回調函數}當你想要發佈到所有用戶的

所以遍歷所有訂戶。

高級方法: 接受一個應具有onMessage函數的類的對象(或任何想要給此方法的名稱),而不接受訂閱API中的簡單函數名稱。然後,您可以簡單地將相同的對象實例傳遞給取消訂閱API以取消註冊。當你需要通知訂閱者時,你可以調用所有訂閱者的instance.onMessage函數。比較兩個對象引用很容易。

3

如果你看一下Node.js的源事件

https://github.com/nodejs/node/blob/master/lib/events.js

你可以看到,核心團隊使用===如何===實現比較功能平等

我不知道函數,但我當然希望它不是toString(),因爲兩個不同的函數可能有相同的toString()結果,LOL

+1

這使用引用相等檢查,與javascript的標準行爲相同:https://github.com/nodejs/node/blob/master/lib/events.js#L329 – SimplGy