JavaScript 对象引用
JavaScript Object Reference
我已经看到很多关于这种情况的问题,但我仍然无法弄清楚我的问题到底是什么。 (我仍在试验 JavaScript,尤其是物体)
代码:
function Field(val)
{ var value = val;
this.__defineGetter__("value", function(){ return value; });
this.__defineSetter__("value", function(val){ value = val; if(this.onchange) this.onchange.call(); });
}
function LW_makePlan()
{
/* [...] */
this.Filter1=new Field("");
this.Filter2=new Field("");
this.Filter3=new Field("");
this.init = function()
{
/* [...] */
this.Filter1.onchange=this.getSomething;
}
this.getSomething = function()
{
arg="modus=doWhat";
arg=arg+"&filter1=" + this.Filter1.value;
arg=arg+"&filter2=" + this.Filter2.value;
arg=arg+"&filter3=" + this.Filter3.value;
request_fkt(null, true, arg , this.setSomething);
}
this.setSomething = function(data)
{
alert(data);
}
this.init();
};
我在尝试什么:
test = new LW_makePlan();
test.Filter1.value="anything";
test.Filter1 有一个 "onchange"-属性,在 "Field" 的 setter 中检查。如果设置,setter 还将调用 onchange-属性.
中给定的对象
目前为止这是有效的,但看起来,这个调用创建了一个全新的对象实例……不,不是一个实例,就好像函数 "getSomething" 被复制为一个独立的函数,因为我调用的代码,但是例如函数 "getSomething" 中的 this.Filter1 未定义 ...
为什么会发生这种情况,我该如何避免这种情况?
PS:我不想使用来自第 3 方代码的某种类型的事件处理,我想在一些帮助下自己做。
编辑:
感谢 Steffen Heil,更改为:
var scope=this;
this.Filter1.onchange=function() { scope.getSomething(); };
而且有效!
您对 this.onchange
的调用在 Field
中,因此您正在调用 Field
的函数。赋值 this.Filter1.onchanged=this.getSomething
将方法 getSomething
从 LW_makePlan
复制到 Field
,它将在其中被调用。
所以在现在称为 onchanged
的 getSomething
中,引用 this
指的是 Field
而不是 LW_makePlan
。
将作业替换为:
var source = this;
this.Filter1.onchange = function() { return source.getSomething(); };
它会起作用的。大多数框架都有一个 bind
方法使它更具可读性(将额外的变量隐藏在一个范围内)。
回复第一条评论:
您可以像这样显式调用函数:
x.call( object, arg1, arg2, ag3 );
x.apply( object, [ arg1, arg2, arg3 ] );
这些都是一样的,x是什么并不重要。在被调用函数中 this
的值为 object
。
x 可以是:
alert
window.alert
(function(){})
(alert)
(window.alert)
函数的正常调用是快捷方式:
object.f = g;
object.f( arg1 ) => g.call( object, arg1 );
f( arg1 ) => f.call( window, arg1 );
虽然window
是浏览器中的全局对象;其他环境可能使用另一个全局对象。
虽然这两个快捷方式之间的区别似乎微乎其微,但以下呢?
(object.f)( arg1 )
这是完全有效的 javascript,因为 object.f
是一个函数,并且可以使用 (args1)
调用函数。但是:
object.f = g;
(object.f)( arg1 ) => g.call( window, arg1 )
所以a.f = b.f;
将成员引用从a
复制到b
,但是this
上下文,代码的执行取决于f
] 被调用。
a.f(x) == a.f.call(a,x) == (a.f).call(a,x) == b.f.call(a,x) == (b.f).call(a,x)
b.f(x) == b.f.call(b,x) == (b.f).call(b,x) == a.f.call(b,x) == (a.f).call(b,x)
顺便说一句,您可以很容易地定义自己的bind
:
function bind( object, method ) {
return function() {
return object[ method ].apply( object, arguments );
};
}
那么原代码会变成:
this.Filter1.onchange = bind( this, 'getSomething' );
这将与我在上面使用 "late binding" 给出的修复相匹配。大多数图书馆更喜欢 "early binding":
function bind( object, method ) {
return function() {
return method.apply( object, arguments );
};
}
那么原代码会变成:
this.Filter1.onchange = bind( this, this.getSomething );
优点是性能更好,但主要区别在于调用绑定后 getSomething
发生变化时发生的情况。第一个实现调用新值,第二个调用旧值。
我已经看到很多关于这种情况的问题,但我仍然无法弄清楚我的问题到底是什么。 (我仍在试验 JavaScript,尤其是物体)
代码:
function Field(val)
{ var value = val;
this.__defineGetter__("value", function(){ return value; });
this.__defineSetter__("value", function(val){ value = val; if(this.onchange) this.onchange.call(); });
}
function LW_makePlan()
{
/* [...] */
this.Filter1=new Field("");
this.Filter2=new Field("");
this.Filter3=new Field("");
this.init = function()
{
/* [...] */
this.Filter1.onchange=this.getSomething;
}
this.getSomething = function()
{
arg="modus=doWhat";
arg=arg+"&filter1=" + this.Filter1.value;
arg=arg+"&filter2=" + this.Filter2.value;
arg=arg+"&filter3=" + this.Filter3.value;
request_fkt(null, true, arg , this.setSomething);
}
this.setSomething = function(data)
{
alert(data);
}
this.init();
};
我在尝试什么:
test = new LW_makePlan();
test.Filter1.value="anything";
test.Filter1 有一个 "onchange"-属性,在 "Field" 的 setter 中检查。如果设置,setter 还将调用 onchange-属性.
中给定的对象目前为止这是有效的,但看起来,这个调用创建了一个全新的对象实例……不,不是一个实例,就好像函数 "getSomething" 被复制为一个独立的函数,因为我调用的代码,但是例如函数 "getSomething" 中的 this.Filter1 未定义 ...
为什么会发生这种情况,我该如何避免这种情况?
PS:我不想使用来自第 3 方代码的某种类型的事件处理,我想在一些帮助下自己做。
编辑:
感谢 Steffen Heil,更改为:
var scope=this;
this.Filter1.onchange=function() { scope.getSomething(); };
而且有效!
您对 this.onchange
的调用在 Field
中,因此您正在调用 Field
的函数。赋值 this.Filter1.onchanged=this.getSomething
将方法 getSomething
从 LW_makePlan
复制到 Field
,它将在其中被调用。
所以在现在称为 onchanged
的 getSomething
中,引用 this
指的是 Field
而不是 LW_makePlan
。
将作业替换为:
var source = this;
this.Filter1.onchange = function() { return source.getSomething(); };
它会起作用的。大多数框架都有一个 bind
方法使它更具可读性(将额外的变量隐藏在一个范围内)。
回复第一条评论:
您可以像这样显式调用函数:
x.call( object, arg1, arg2, ag3 );
x.apply( object, [ arg1, arg2, arg3 ] );
这些都是一样的,x是什么并不重要。在被调用函数中 this
的值为 object
。
x 可以是:
alert
window.alert
(function(){})
(alert)
(window.alert)
函数的正常调用是快捷方式:
object.f = g;
object.f( arg1 ) => g.call( object, arg1 );
f( arg1 ) => f.call( window, arg1 );
虽然window
是浏览器中的全局对象;其他环境可能使用另一个全局对象。
虽然这两个快捷方式之间的区别似乎微乎其微,但以下呢?
(object.f)( arg1 )
这是完全有效的 javascript,因为 object.f
是一个函数,并且可以使用 (args1)
调用函数。但是:
object.f = g;
(object.f)( arg1 ) => g.call( window, arg1 )
所以a.f = b.f;
将成员引用从a
复制到b
,但是this
上下文,代码的执行取决于f
] 被调用。
a.f(x) == a.f.call(a,x) == (a.f).call(a,x) == b.f.call(a,x) == (b.f).call(a,x)
b.f(x) == b.f.call(b,x) == (b.f).call(b,x) == a.f.call(b,x) == (a.f).call(b,x)
顺便说一句,您可以很容易地定义自己的bind
:
function bind( object, method ) {
return function() {
return object[ method ].apply( object, arguments );
};
}
那么原代码会变成:
this.Filter1.onchange = bind( this, 'getSomething' );
这将与我在上面使用 "late binding" 给出的修复相匹配。大多数图书馆更喜欢 "early binding":
function bind( object, method ) {
return function() {
return method.apply( object, arguments );
};
}
那么原代码会变成:
this.Filter1.onchange = bind( this, this.getSomething );
优点是性能更好,但主要区别在于调用绑定后 getSomething
发生变化时发生的情况。第一个实现调用新值,第二个调用旧值。