我已经看到很多关于这种情况的问题,但我仍然无法弄清楚,究竟我的问题是什么。 (我还在尝试使用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" -property,在" Field"的setter中检查。如果设置,setter也将调用onchange-property中给出的对象。
这到目前为止工作但看起来,这个调用创建了一个全新的对象 - 实例......不是一个实例,就像函数" getSomething"被复制为一个独立的函数,因为我调用了代码,但是例如函数中的this.Filter1" getSomething"未定义......
为什么会发生这种情况?我该如何避免这种情况?
PS:我不想使用某种类型的事件处理 - 来自第三方代码的东西,我想自己做一些帮助。
编辑:
感谢Steffen Heil,改为:
var scope=this;
this.Filter1.onchange=function() { scope.getSomething(); };
它有效!
答案 0 :(得分:1)
您对this.onchange
的来电位于Field
,因此您正在调用Field
的函数。作业this.Filter1.onchanged=this.getSomething
将getSomething
方法从LW_makePlan
复制到Field
,并将其调用。{/ p>
因此getSomething
内部现在称为onchanged
,引用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' );
这将匹配我上面使用"后期绑定"的修复。大多数图书馆更喜欢"早期绑定":
function bind( object, method ) {
return function() {
return method.apply( object, arguments );
};
}
然后原始代码将成为:
this.Filter1.onchange = bind( this, this.getSomething );
优点是性能更好,但主要区别在于调用bind后getSomething
更改时发生的情况。第一个实现调用新值,第二个实现调用旧值。