[英]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. 问题是您没有适合于
this
的this.options
对象,而只有一个对象与具有相同原型的所有对象共享。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.