Javascript常量设置变量

时间:2012-12-13 20:21:51

标签: javascript jquery

运行此代码时,构造函数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");}如何成为原型的常量值?

2 个答案:

答案 0 :(得分:2)

这一切都从这一行开始:

this.callback = callbacks.callback;

当您拨打电话new Test(eins)时,eins会以callbacks参数的形式出现。然后该行将this.callback(即新的Test实例上的“callback”属性)设置为callbacks的回调属性,即。 eins

现在,仅此一点不会影响B.但是,有一些棘手的事情:

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

您会认为这会在您的Test实例上设置“options”属性,对吗?错误。 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);

答案 1 :(得分:1)

当你这样做时

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

您将原型的options.complete函数替换为始终以this作为上下文的函数。

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