我知道如何解决这个特殊问题,但我想知道为什么会这样。基本上,当我尝试调用这样的函数时:
(callFoo ? this.foo : this.bar)();
它调用了正确的foo函数,但在foo中,this
是全局的window对象而不是我期望的对象。
我希望这会做同样的事情,但事实并非如此:
(this.foo)();
上面的代码调用了正确的函数并维护了正确的上下文(this
就是我所期望的那样)。
Here is a jsfiddle for you to play around with.
有人可以解释一下发生了什么吗?我理解如何解决这个问题(我甚至不是那种语法的粉丝),但是如果从三元运算符返回一个函数,我仍然想知道为什么this
成为窗口。
修改
我想改进我的问题:
对我来说这是有意义的:
(callFoo ? this.foo : this.bar)();
相当于:
var f = (callFoo ? this.foo : this.bar);
f();
对我来说,this
成为该函数中的窗口是有道理的。
为什么不会发生同样的事情:
(this.foo)();
答案 0 :(得分:2)
要拥有正确的上下文调用对象,请将其命名为
this[ callFoo ? 'foo' : 'bar' ]();
this
的值始终取决于您调用函数的 。你基本上就像调用
fnc();
导致this
始终为全局 / 窗口(在非严格模式下)。您需要将此函数作为方法 / 属性调用,如this.fnc()
。在这种情况下,this
将默认引用调用对象。
答案 1 :(得分:1)
此表达式在逻辑上等同于以下内容:
var tempFun;
if(callFoo) {
tempFun = this.foo;
} else {
tempFun = this.bar;
}
tempFun();
这是丢失this
引用的经典示例。如你所说,你知道解决方法/解决方案:
tempFun.call(this);
或:
(callFoo ? this.foo : this.bar).call(this)
答案 2 :(得分: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被视为已传递的方法,而不是通过'。'绑定到对象的方法。关联。
答案 3 :(得分:0)
使用三元运算符时,您要在两个函数之间进行选择。这与执行以下操作类似:
var func = this.foo;
foo(); // Inside this call, "this" will now refer to the global context
// -- "window" in a browser environment
这个(即“this”)是JavaScript中最棘手的事情之一,并且已经写了很多。
当您在“this.foo”周围抛出问题时,问题也不会发生,这有点令人惊讶。但这不是你的问题: - )