两个匿名函数的平等

时间:2014-08-31 18:47:54

标签: javascript anonymous-function reference-type

我有以下代码

var arr = [];
$("#Target").click(function () {
    function Stuff() {
        console.log("Dummy");
    }
    var found = false;
    for (var i = 0; i < arr.length; i++) {
        found = found || arr[i] == Stuff;
    }
    if (!found)
        arr.push(Stuff);
    alert(arr.length);
});

每次单击按钮都会增加数组的计数。但是,如果我像这样修改代码

function Stuff() {
    console.log("Dummy");
}
var arr = [];
$("#Target").click(function () {
    var found = false;
    for (var i = 0; i < arr.length; i++) {
        found = found || arr[i] == Stuff;
    }
    if (!found)
        arr.push(Stuff);
    alert(arr.length);
});

它检测到相等性,数组最多包含1个元素。 这里发生的事情是每次触发click事件时,都会再次实例化匿名处理程序,Stuff函数也是如此。 在第一个代码块中,每次触发事件时都会实例化匿名函数。在第二个代码块中,因为Stuff函数是一个全局函数(读取&#34; window对象的属性&#34;)它没有实例化。

我的问题是,是否有一种确定的方法来测试这种功能的平等性?

PS:我知道有一种解决方法,比如

arr[i].toString() == Stuff.toString();

但我想抑制这种&#34;巫术&#34;

修改

更多细节:我想创建一个函数

$.throttle = function(func, delay){
    // Here I need to check whether this function was already passed,
    // and if yes, I need to clear previous timeout and create new
}

可以像这样调用

$.throttle(function () { console.log("Foo"); }, 5000);

2 个答案:

答案 0 :(得分:3)

  

这里发生的是每次click事件被触发时,匿名处理程序再次被实例化,Stuff函数也被实例化。

不,这不是你的第二个代码块中发生的事情。每次click触发时,相同的 Stuff函数都会被推送到数组中;匿名函数只由click处理程序运行,而不是由实例化运行。 (它由代码连接click处理程序实例化。)

如果您有两个对函数的引用并想知道它们是否引用相同的函数,您可以将它们与=====进行比较:

var ref1 = Stuff;
var ref2 = Stuff;
console.log(ref1 === ref2);  // true
console.log(ref1 === Stuff); // true
console.log(ref2 === Stuff); // true

如果要创建函数的两个不同副本(如在第一个代码块中)并查看它们是否具有相同的代码,则没有正式的方法可以执行此操作。你可以比较你所指出的toString的结果(尽管规范实际上并不需要toString来返回代码),但是那会比较它们的代码内容(如果它有效),它不会比较他们的上下文。考虑:

function foo(bar) {
    return function() {
        alert(bar);
    };
}
var f1 = foo("one");
var f2 = foo("two");
f1();                                         // alerts "one"
f2();                                         // alerts "two"
console.log(f1.toString() === f2.toString()); // true

我们从调用foo返回的函数中包含相同的代码,但它们不是等效的函数。据我所知,没有标准的方法来比较等价的函数,仅用于身份。

答案 1 :(得分:1)

函数(在 JavaScript 中)是 Objects (function () {}) instanceof Object,并且 Objects 的相等性已完成 ByRef ,即相同不相等

如果你想做你所描述的事情,你需要对引用有一个闭包,这样你就可以访问它,也许你想要这样的东西

var arr = [];
$("#Target").click((function () {
    function Stuff() {
        console.log("Dummy");
    }
    return function () {
        var found = false;
        for (var i = 0; i < arr.length; i++) {
            found = found || arr[i] == Stuff;
        }
        if (!found)
            arr.push(Stuff);
        alert(arr.length);
    };
}()); // note IIFE execution

这里有什么不同? Stuff仅创建一次,但由return ed函数使用,该函数将成为单击处理程序

如果你想传递可能在其他地方定义的抽象函数,你可以将它作为 IIFE 的参数/参数

function foo() {
    // ...
}

$("#Target").click((function (Stuff) {
    return function () {
        // `foo` is called `Stuff` here
    };
}(foo));