我正在使用一个函数来创建将在文档事件处理程序上使用的其他函数,因此返回函数的签名必须与事件处理程序的签名匹配,例如。 function (event, ui)
.
代码如下
function createEventHandler(refFn, additionalMods) {
var createdEvent = function (event, ui) {
// Merge the properties of additionalMods with an object { event, ui }
// call function with refFn and the resulting object as parameters
}
createdEvent.ready = true;
return createdEvent;
}
为了清楚起见,我删除了生成函数的代码,但在 refFn
内和additionalMods
变量在内部进行处理。
现在,在处理用户输入时,我调用以下行
var handler = events[i].handler.ready ?
events[i].handler :
createEventHandler(events[i].handler);
基本上处理一个数据数组,每个数据数组都有一个名为 handler 的属性,该属性可以是函数,也可以是调用 createEventHandler 的结果。
底线是,如果数组中的函数已被处理,则“按原样”传递该函数,如果没有处理该函数并存储结果,那么最后所有函数都会被处理。
现在我正在附加一个名为“ready”的属性来表示该函数已被处理,因为事实证明没有可靠的方法可以根据 this post 获取函数的名称。但这感觉不对。
我也尝试使用原型(prototype)进行比较,但这不起作用,因为每次都会创建一个新函数并且位于作用域内,因此我无法获得用于比较的引用。
我什至尝试过
events[i].handler.prototype == createEventHandler().prototype
但是当然没用。
有谁知道我如何生成这个函数,并有一个可靠的方法来比较它们,以了解它们是否是由我的代码生成的。
{编辑}
添加进一步说明
上面的所有代码都在同一范围内,这意味着处理数组的代码对createEventHandler
具有可见性。功能。我可以修改这段代码,但我无法修改的是创建数组后的内容。我必须在它出现时对其进行迭代,并根据工作是否已经完成来生成或不生成。
createEventHandler 还通过 API 函数向用户公开。假设用户调用 evt.generate('model')
这将生成一个事件处理程序,该处理程序在幕后使用 createEventHandler 函数执行特定的工作。如果那么您可以调用evt.generate('bind')
将生成另一个执行其他工作的。
默认情况下向用户提供了很多行为,但如果没有任何预定义行为适合该任务,他们可以选择添加自定义行为。
所有数据都声明一次,但数组的内容是不同的,因为我可以编写以下内容并且应该可以工作。我省略了大部分其他不相关的属性。
var events = [
{
event: 'pageshow',
handler: evt.generate('model')
},
{
event: 'pagebeforeshow',
handler: function (params, last) {
// My custom handler for this case
}
}
];
循环数组后,所有处理程序都采用相同的格式并准备好绑定(bind)。 createEventHandler
在所有情况下都是必要的,因为我使用依赖项注入(inject)来为这些参数提供数据,所以它基本上是“如果尚未调用,则调用它并执行所有依赖项注入(inject)工作”,这就是我需要比较函数的原因。
最佳答案
我找到了一个优雅的解决方案,并将其发布在这里,以防有人遇到同样的问题。
我的代码的问题是,用户汽车编写了一个函数,该函数具有名为 ready
的属性(这是一个通用名称)和一个值 true
(这也是一个通用名称)值并且处理将失败。
也许用户没有编写该属性,也许是因为继承自其原型(prototype)而存在。目标是尝试尽可能确定您正在处理的代码是否是输出或您自己的函数,这在 javascript 中几乎是一项不可能完成的任务。
我发现的最准确的方法是当我阅读 Equality comparisons and sameness 时它告诉我,当您使用 ===
相等运算符时,对象仅等于其自身,并且不是原始对象。那就是
undefined === undefined => true
null === null => true
"foo" === "foo" => true
0 === 0 => true
但是
{a:1} === {a:1} => false
因此,您可以编写一个与对象相等的属性,并且当您持有对该对象的引用时,如果您未设置该属性,则所有比较都将失败。
这很好,但有一个名为“ready”的额外属性与一个随机对象进行比较感觉很糟糕,也许有更好的方法,是的,有。
在 javascript 中没有类,但有原型(prototype)继承,因此您可以编写一个函数并使用其中一种继承模式将此函数设置为您的祖先函数并使用它进行比较。
var parentEvent = function () {};
// This is the function that will be used as parent
function createEventHandler(refFn, additionalMods) {
var createdEvent = function (event, ui) {
// Merge the properties of additionalMods with an object { event, ui }
// call function with refFn and the resulting object as parameters
}
//createdEvent.ready = true This is no longer necessary
// This is the "sharing prototype" inheritance pattern
createdEvent.prototype = parentEvent.prototype
return createdEvent;
}
现在返回函数的原型(prototype)指向您保存在变量中的函数。然后您可以使用比较它们
// Replace the property comparison with the prototype comparison
var handler = events[i].handler.prototype === parentEvent.prototype ?
events[i].handler :
createEventHandler(events[i].handler);
我知道,这并不能保证失败,但对于大多数情况来说已经足够了。
{编辑}
感谢@Bergi 指出这不是严格意义上的继承。原因是大多数 javascript 继承模式要求您使用 constructor functions我在这里使用工厂函数。为了让它工作,你必须写这样的东西
function createEventHandler(refFn, additionalMods) {
// Same code as before
createdEvent.prototype = parentEvent.prototype
return new createdEvent();
}
比较完成
events[i].handler.__proto__ === parentEvent.prototype
请注意函数返回方式与新 prototype
属性访问方式的差异。当您想要返回父函数中的其他属性时,这非常有用。
关于javascript - 当函数作为另一个函数的结果创建时如何比较该函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30513709/