2

我知道如何解决这个特殊问题,但我想知道它为什么会发生。基本上,当我尝试调用这样的函数时:

(callFoo ? this.foo : this.bar)();

它调用了正确的 foo 函数,但在 foo 内部,this是全局的窗口对象,而不是我期望的对象。

我希望这会做同样的事情,但它不会:

(this.foo)();

上面的代码调用了正确的函数并维护了正确的上下文(this这是我所期望的)。

这是一个 jsfiddle 供您使用。

有人可以解释发生了什么吗?我知道如何解决这个问题(我什至不喜欢这种语法),但我仍然想知道this如果你从三元运算符返回一个函数,为什么会变成窗口。


编辑
我想完善我的问题:这对我来说很有意义:

(callFoo ? this.foo : this.bar)();

相当于:

var f = (callFoo ? this.foo : this.bar);
f();

这对我来说很有意义,为什么this会成为该功能中的窗口。

为什么这里没有发生同样的事情:

(this.foo)();
4

4 回答 4

2

要拥有正确的上下文调用对象,请将其称为

this[ callFoo ? 'foo' : 'bar' ]();

always的值this取决于调用函数的方式。您基本上是在调用该函数,就像

fnc();

这导致this始终是全局/窗口(在非严格模式下)。您需要将函数作为方法/属性调用,例如this.fnc(). 在这种情况下,this将默认引用调用的对象。

于 2012-10-04T21:23:26.007 回答
1

这个表达式在逻辑上等价于这样的:

var tempFun;
if(callFoo) {
    tempFun = this.foo;
} else {
    tempFun = this.bar;
}
tempFun();

这是失去this参考的经典例子。正如您所说,您知道解决方法/解决方案:

tempFun.call(this);

或者:

(callFoo ? this.foo : this.bar).call(this)
于 2012-10-04T21:31:36.123 回答
1

产生差异的原因:

var obj = new (function MyConstructor(){
    this.getConstructor = function(){ return this.constructor.name; }
});

当任何运算符对操作数进行操作时,结果的工作方式与函数的返回值非常相似。传递的对象方法不再被视为绑定到对象。

(function(){ return obj.getConstructor; })(); //'Window'

但是,如果除了属性访问之外在括号内没有发生任何事情,则括号会被简单地忽略,而不是被视为运算符本身。所以:

(obj.getConstructor)(); //'MyConstructor'

真的只是相当于:

obj.getConstructor();

但是添加任何类型的有效操作都会导致该方法:

(false || obj.getConstructor)(); //'Window'

并且 obj.getConstructor 被视为已传递的方法,而不是通过“。”绑定到对象的方法。协会。

于 2012-10-04T21:54:26.417 回答
0

当您使用三元运算符时,您是在两个函数之间进行选择。这类似于执行以下操作:

var func = this.foo;
foo(); // Inside this call, "this" will now refer to the global context
       // -- "window" in a browser environment

this(即“this”)是 JavaScript 中最棘手的事情之一,并且已经写了很多关于它的文章。

当你在“this.foo”周围加上括号时,这个问题也不会发生,这有点令人惊讶。但这不是你的问题:-)

于 2012-10-04T21:30:22.347 回答