我有以下代码
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);
答案 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));