简体   繁体   English

Javascript常量设置变量

[英]Javascript Constant Setting Variable

When running this code, the whatever value is first passed in with the constructor Test(callbacks) becomes the callback that is always called, even in later instantiations of Test 运行此代码时,无论构造函数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();

Running this code, every time you will get the output AAA . 运行此代码,每次您将获得输出AAA How does function() {console.log("AAA");} become a constant value for the prototype? function() {console.log("AAA");}成为原型的常量值?

It all starts with this line: 一切都从这一行开始:

this.callback = callbacks.callback;

When you make a call new Test(eins) , eins comes in as the callbacks argument. 当您调用new Test(eins)eins作为callbacks参数进入。 That line then sets this.callback (ie. the "callback" property on your new instance of Test) to the callback property of callbacks , ie. 那行然后将this.callback (即“回调”您的新测试实例属性),以回调财产callbacks ,即。 of eins . eins

Now, that alone wouldn't affect B. However, there's something tricky: 现在,仅此一项不会影响B。但是,有些棘手的事情:

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

You would think that that would set the "options" property on your Test instance, right? 您会认为这将在您的Test实例上设置“ options”属性,对吗? Wrong. 错误。 The way Javascript works is that if a property isn't defined on your instance (eg. you didn't do this.options = something ) then Javascript will look up the "prototype chain", where it will find the prototype's "options", and set it (not your instance's "options", since your instance doesn't have one). Javascript的工作方式是,如果未在实例上定义属性(例如,您未执行this.options = something ),则Javascript将查找“原型链”,在该链中可以找到原型的“ options” ,然后进行设置(而不是您实例的“选项”,因为您的实例没有一个)。

You can fix all this by changing that line to: 您可以通过将该行更改为以下内容来解决所有问题:

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

but of course that would lose your type: "GET", so either you need to do: 但当然会丢失您的type: "GET",因此您需要执行以下操作:

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

or you need to base your options off the prototype's: 或者您需要基于原型的选项:

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

If you happen to be using the (excellent) Underscore library, it even has an extend function for doing this sort of thing more easily: 如果您碰巧正在使用(出色的)Underscore库,它甚至还具有extend功能,可以更轻松地执行此类操作:

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

Or (depending on your style preferences): 或(取决于您的样式偏好):

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

Incidentally, Underscore also has a _.bind method which is comparable to jQuery's "proxy", so you could also do: 顺便说一下, _.bind也有一个_.bind方法,该方法与jQuery的“代理”相当,因此您也可以这样做:

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

When you do 当你做

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

You're replacing the options.complete function of the prototype by one that will always have this as context. 您将用始终将this作为上下文的那个替换原型的options.complete函数。

The problem is that you don't have a this.options object proper to this , but only one shared with all objects having the same prototype. 问题是您没有适合于thisthis.options对象,而只有一个对象与具有相同原型的所有对象共享。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM