为什么我会丢失Javascript中的上下文?
我有一个简单的代码:为什么我会丢失Javascript中的上下文?,javascript,Javascript,我有一个简单的代码: var o = { a: 1, b: 2, f1: function () { alert(this.b); } } var o2 = { a: 11, b: 22, f2: function (j) { j(); } } 但运行此代码: o2.f2(o.f1)产生未定义的结果。(我希望结果是“22”) 现在,我知道上下文已经到了某个地方。因此,如果我将o2中
var o = {
a: 1,
b: 2,
f1: function ()
{
alert(this.b);
}
}
var o2 = {
a: 11,
b: 22,
f2: function (j)
{
j();
}
}
但运行此代码:
o2.f2(o.f1)
产生未定义的结果。(我希望结果是“22”)
现在,我知道上下文已经到了某个地方。因此,如果我将o2
中的代码更改为:
f2: function (j)
{
j.apply(this);
}
很明显,它确实有效
但我的问题是:
- 我在什么阶段失去了背景李>
j()
时,o2
对象中有一个b
属性
我错过了什么
如果您按照以下方式操作 函数将在o2上下文中调用
var o2 = {
a: 11,
b: 22,
f2: function (j){
this.temp = j;
this.temp();
}
};
这些也将起作用:
f2: function (j){
j.apply(this);
}
f2: function (j){
j.apply(o2);
}
否则,调用它就像在上下文之外调用普通函数一样
j脱离了它的上下文,您没有对它进行复杂的闭包(这不是您的意图),所以要使“这个”在其中工作,您需要一个范围。您问题中j的范围是窗口,窗口中没有“b”,因此您会得到一个“未定义的”。检查此测试:
o.f1(); // alerts 2
var f3 = o.f1; // (*)
f3(); // alerts undefined
o2.f2(f3); // alerts undefined
f3.apply(o2); // alerts 22
我意识到,当您将函数作为参数传递时,上下文的丢失方式与上面代码中指出的(*)
中的丢失方式完全相同
发生的是j=arguments[0]=o.f1
,此时您将失去上下文
当将函数作为参数传递时,您只是将内存中的引用传递给该函数。如果不绑定上下文,简单的
j()
调用将失败。这就是为什么你需要使用apply
或者Ihsan展示的this
技巧。我发现Crockford对这种工作方式有很好的描述。JavaScript中的函数可以以4种样式调用:
// function invocation style,
var f = function() { console.debug(this); }
f(); // "this" is bound to the global object.
// "method" invocation style
var obj = {
f: function() { console.debug(this); }
};
obj.f(); // "this" is bound to "obj", the object on which the function was invoked
// so important bit is :
var f = obj.f;
f(); // "this" is global object
obj.f() // "this" is obj
在您的示例中,由于调用函数的方式,您正在丢失“this”。当您将其称为
f()
-JavaScript方法是“未绑定函数”(也就是说,与其他语言中的方法不同,它们不与特定对象/实例相关联)调用时,由调用站点决定此。(当然,请参阅或等效的仿真。)您一绕过o.f1
就会丢失它。如果您执行var x=o.f1
并调用x()
,f1
将不再绑定。@Blender我知道。但是为什么这个
不是关于o2
?这是我不知道的understand@RoyiNamirf()
大致相当于window.f=f;window.f()@罗伊纳米尔:为什么要这么做?它是未绑定的。调用它不会神奇地将它绑定到当前上下文。