我在以下代码中对变量tmp
的要点感到不安:
$.extend($.Widget.prototype, {
yield: null,
returnValues: { },
before: function(method, f) {
var original = this[method];
this[method] = function() {
f.apply(this, arguments);
return original.apply(this, arguments);
};
},
after: function(method, f) {
var original = this[method];
this[method] = function() {
this.returnValues[method] = original.apply(this, arguments);
return f.apply(this, arguments);
}
},
around: function(method, f) {
var original = this[method];
this[method] = function() {
var tmp = this.yield;
this.yield = original;
var ret = f.apply(this, arguments);
this.yield = tmp;
return ret;
}
}
});
为什么不简单地使用函数局部变量var yield
并在tmp
方法中完全省略around
?它有什么用途?这是一种常见的设计模式吗?
感谢您提供一些提示。
答案 0 :(得分:0)
显然,代码来自Extending jQuery UI Widgets,它提供了一些有用的上下文。该文引用Avoiding Bloat in Widgets作为代码的来源。但是,原始版本没有tmp
变量。
我喜欢添加tmp
,因为它避免了原始代码带来的副作用。考虑如何使用around函数:
YourWidgetObject.existingWidgetClass("around", "click", function(){
console.log("before"); //or any code that you want executed before all clicks
yield(); // executes existing click function
console.log("after"); //or any code that you want executed after all clicks
}
无论是否有tmp
杂耍,这都可以正常工作。 click
事件现在将在事件之前和之后执行您的额外代码。
但如果您不使用yield
恢复tmp
,则现在将重新定义对象的公共方法yield
。因此,如果有人在使用YourWidgetObject.yield()
之后只是调用around
会有一个奇怪的想法,它会执行上次应用的任何现有方法around
(在这种情况下,click
)。
在澄清请求后添加:
想象一下,您根本不会恢复yield
,也不会将其设置为null。在上面的代码之后,你这样做:
YourWidgetObject.existingWidgetClass("before", "focus", function(){
yield(); // executes existing **click** function
}
yield
现在执行焦点上的单击功能,这是非常意外的行为。
您是否可以将yield
设置为null,而不是使用tmp
进行恢复?当然,就像现在一样,它不会有所作为。但是,正如您可能更改或添加其他方法一样,使around
方法不知道当前状态更为谨慎,即它不应该知道yield
始终是它被调用时为null。
作为一个旁注,我认为这是一个糟糕的around
方法,因为把事情放在一个事件不一定是它的作用 - 你可以多次调用yield
,或者不是所有。真正的around
方法更明智的是接受两个回调,一个在事件之前执行,一个在之后执行。这样,您就不需要首先公开yield
方法。
around: function(method, before, after) {
var original = this[method];
this[method] = function() {
before();
original();
after();
}
}