我有这个简单的代码:
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)
会产生 undefined 。 (虽然我期待“22”因此)
现在,我知道背景已经到了某个地方。因此,如果我将o2
中的代码更改为:
f2: function (j)
{
j.apply(this);
}
它确实有效。
但我的问题是:
我不明白:当j()
正在运行时, <{1}}对象中的b
属性。
我错过了什么?
答案 0 :(得分:6)
我发现克罗克福德对其运作方式有很好的描述。 JavaScript中的函数可以用4种样式调用:
我可能会在那里得到错误的名字,但精神是一样的。如果你没有它,你肯定会得到“JavaScript:The Good Parts”这本书。
所以无论如何 - 关于你的问题。关键是“this”的值取决于您使用的样式。
// 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”。
答案 1 :(得分:1)
如果你这样做,
函数将在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被撕掉它的上下文并且你没有对它进行任何棘手的关闭(这不是你的意图)所以为了让“this”在其中工作,你需要一个范围。你在j的问题中的这个范围是窗口,它没有“b”,因此你得到一个“未定义的”。
答案 2 :(得分:0)
检查此测试:
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()
调用。这就是为什么你需要使用Ihsan所展示的apply
或this
技巧。