这段代码中变量“tmp”的用途是什么?

What's the purpose for the variable `tmp` in this snippet?

我很难理解以下代码中变量 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 并在 around 方法中完全省略 tmp?它有什么作用?这是常见的设计模式吗?

感谢您的提示。

显然该代码来自 Extending jQuery UI Widgets, which provides some useful context. That article refers to 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 事件现在将在事件前后执行您的额外代码。

但是如果您不使用 tmp 恢复 yield,对象的 public 方法 yield 现在将被重新定义。因此,如果有人有在使用 around 之后调用 YourWidgetObject.yield() 的奇怪想法,它将执行上次应用的任何现有方法 around(在本例中,click ).

在要求澄清后添加:

假设您根本不恢复 yield,也不将其设置为空。在上面的代码之后,你这样做:

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();
    }
}