2

运行此代码时,首先使用构造函数传入的任何值都将Test(callbacks)成为始终调用的回调,即使在以后的实例化中也是如此Test

function Test(callbacks) {
    if (callbacks) {
        if (callbacks.callback) {
            this.callback = callbacks.callback;
        }
    }

    this.options.complete = $.proxy(this.options.complete, this);
}

Test.prototype = {
    options: {
        type: "GET",
        complete: function() {
            this.callback();
        }
    },
    callback: function() { console.log("OVERRIDE ME"); },

    execute: function() {
        $.ajax(this.options);
    }
};

var eins = {callback: function() {console.log("AAA");}};
var zwei = {callback: function() {console.log("BBB");}};

var A = new Test(eins);
var B = new Test(zwei);

A.execute();
B.execute();

运行这段代码,每次你都会得到输出AAA。如何function() {console.log("AAA");}成为原型的常量值?

4

2 回答 2

1

一切都从这一行开始:

this.callback = callbacks.callback;

当你打电话new Test(eins)时,作为参数eins进来。callbacks然后,该行将this.callback(即新的 Test 实例上的“回调”属性)设置为 的回调属性callbacks,即。的eins

现在,仅此一项不会影响 B。但是,有一些棘手的问题:

this.options.complete = $.proxy(this.options.complete, this);

您会认为这会在您的测试实例上设置“选项”属性,对吧?错误的。Javascript 的工作方式是,如果您的实例上没有定义属性(例如,您没有定义this.options = something),那么 Javascript 将查找“原型链”,它会在其中找到原型的“选项”,并设置它(不是您的实例的“选项”,因为您的实例没有)。

您可以通过将该行更改为:

this.options = {complete: $.proxy(this.options.complete, this)};

但当然这会失去你type: "GET",,所以你需要这样做:

this.options = {type: "GET", complete: $.proxy(this.options.complete, this)};

或者您需要基于原型的选项:

this.options = {};
for (var key in this.prototype.options) {
    this.options[key] = this.prototype.options[key];
}
this.options.complete = $.proxy(this.options.complete, this);

如果你碰巧在使用(优秀的)Underscore 库,它甚至有一个extend功能可以更轻松地完成这类事情:

this.options = _.extend({}, this.prototype.options,
                        {complete: $.proxy(this.options.complete, this)});

或者(取决于您的风格偏好):

this.options = _.extend({}, this.prototype.options);
this.options.complete = $.proxy(this.options.complete, this);

顺便说一句,Underscore 也有一个_.bind可以与 jQuery 的“代理”相媲美的方法,所以你也可以这样做:

this.options = _.extend({}, this.prototype.options);
this.options.complete = _.bind(this.options.complete, this);
于 2012-12-13T20:27:49.703 回答
0

当你这样做

    this.options.complete = $.proxy(this.options.complete, this);

您将options.complete原型的功能替换为始终具有this上下文的功能。

问题是您没有this.options适合的对象this,但只有一个与具有相同原型的所有对象共享。

于 2012-12-13T20:27:39.980 回答