将函数引用或函数名称传递给 _Widget.connect() 时的不同行为

Different behavior when passing function reference or function name into _Widget.connect()

我有一个自定义小部件。该小部件具有连接到 DOM 节点的单击事件的功能。稍后我想将第二个功能连接到第一个功能。

然而,这只有在我首先将函数名称而不是函数引用传递给 connect 函数时才有效。

这会起作用:

this.connect(this.domNode, 'onclick', 'onClick' /*<-- Function name*/);
this.connect(this, 'onClick', 'onClick2');

这不会:

this.connect(this.domNode, 'onclick', this.onClick /*<-- Function reference*/);
this.connect(this, 'onClick', 'onClick2');

Here 是一个 fiddle 演示行为。当您单击带有文本 'Function name' 的小部件时,将显示两个警报,当您单击带有文本 'Function reference' 的小部件时,将仅显示一个警报。

这是某种错误还是我误解了什么?

这不是错误,而是预期的行为。您得到不同结果的原因是 Dojo 维护 "before" 和 "after" 的方式。先解释一下,调用的区别。

this.connect(this.domeNode, 'onclick', 'onClick'); 的情况下,您正在为函数传递一个字符串参数。在内部它会调用类似 this['onClick']() 的东西,这里的功能与小部件中的功能相同(也维护范围,即小部件)。

在第二种情况下,您将函数参数作为函数的实例传递(您也可以创建一个 var functionParam = this.onClick 并将其作为参数传递,这将是相同的),因为它是已经是一个函数,dojo 将执行类似 functionParameter() 的东西(这里的范围也是小部件)。由于两种情况下的范围和功能相同,因此函数的执行方式或输出结果没有区别。

转到有趣的部分,当您设置要在执行原始函数后调用的另一个函数时。 Dojo 必须在某处维护此信息,因此它将您的原始函数替换为 object/function,其中包含所有信息,如 after, before and original function。并且它有一个机制来按顺序执行它们。

所以回答你的问题,第一种情况,dojo 内部会执行它替换你的函数的方法,因此也会调用第二个函数。在第二种情况下,将调用您传递的方法的实例而不是小部件的函数(widget.onClick),因此不会调用第二个函数。

也避免使用connect,这是一个弃用的方法,内部将使用dojo/ondojo/aspect。您不妨使用它们并减少 Dojo 为您做这件事的间接费用。

Deprecated, will be removed in 2.0, use this.own(on(...)) or this.own(aspect.after(...)) instead.