2012-08-31 33 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