【问题标题】:Javascript Constant Setting VariableJavascript 常量设置变量
【发布时间】:2012-12-13 20:21:51
【问题描述】:

运行此代码时,首先使用构造函数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();

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

【问题讨论】:

标签: javascript jquery


【解决方案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);

【讨论】:

  • 我从来没有说过不是 :-) 问题是“function() {console.log("AAA");} 如何成为原型的常量值?”,而答案是它发生在那一行。
  • FWIW,jQuery 也有 $.extend,但我同意,Underscore 是一个不错的库。幸运的是,OO JS 对我来说并不常见。
  • jQuery 扩展和下划线之间有一些细微的区别,但我不记得有什么区别,所以在我的示例中我坚持使用下划线。但是,是的,你也可以完全使用 jQuery。
【解决方案2】:

当你这样做时

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 2010-11-04
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 2014-01-23
    相关资源
    最近更新 更多