【问题标题】:Scope and OR operator in JavascriptJavascript 中的范围和 OR 运算符
【发布时间】:2015-12-15 19:44:47
【问题描述】:

我今天在做一些 JS 代码时踩到了一些奇怪的东西。

如果属性存在,我想执行一个对象的方法,如果不存在,我想执行一些其他函数。 感觉有点花哨,我写了这样的东西:

var obj = {
    method: function(){
        console.log(this);
    }
}

(obj.method || some_other_function)();

如果存在则执行obj.method,否则执行some_other_function

但是在执行 obj.method 时,this 关键字指的是 window 对象,我完全不知道为什么。
请注意,执行 (obj.method)(); 会得到预期的结果(这指的是我的对象)

显然我不需要这种语法来运行我的代码,但我真的很想知道这里发生了什么。

我在这里或其他地方都找不到任何答案,我找到的最接近的东西是this interesting post,但它不包括这个特定情况。

有人知道那里发生了什么吗?

这里有一个fiddle 展示实际操作!

【问题讨论】:

  • 我建议您阅读这篇文章(冗长但解释清楚):github.com/getify/You-Dont-Know-JS/blob/master/…
  • 感谢您的链接!我尝试阅读内容,观看内容,并且在编写代码时会找到自己的方式,但是 JS 肯定有一些非常具体的功能!这篇文章好像很详细,再次感谢!

标签: javascript scope this logical-operators


【解决方案1】:

(obj.method || some_other_function)(); 本质上等同于:

var f = obj.method || some_other_function;
f();

在调用它之前,您已经通过 运行该函数,从而使该函数脱离了 obj 的上下文。

【讨论】:

  • 你还需要解释为什么(obj.method)();var f = obj.method; f();不一样;)
  • 哎呀,我可能误解了'this'关键字......直到现在我才玩过执行上下文,这可以解释我在JS中遇到的一些奇怪的其他错误o_O谢谢你清晰简洁的解释! (这是关于 SO 的第一个问题:)
  • @plalx 我猜没有某些运算符的括号不会改变它包含的表达式,因此没有隐式中间变量?我承认我一开始并没有弄清楚(这确实是我写(obj.method)();作为比较的原因:)
【解决方案2】:

对于学习 JavaScript 的人来说,您的困惑很常见,并且源于对 this 的不完全理解。简短的回答是您的代码正在执行obj.method()some_other_function()。被调用函数内部的this 的上下文是指调用该函数的对象。在调用method 函数(简单地调用obj.method())的典型用例中,obj 调用method,因此this 指的是函数块中的obj

但是,表达式(obj.method || some_other_function)() 似乎没有被任何对象调用,它只是……被调用了,对吧?实际发生的是这个表达式是从全局空间调用的,在浏览器中,它是window 对象。所以你可以认为你的代码是这样执行的:

obj : {
    method: function(){
        console.log(this);
    }
}

window.(obj.method || some_other_function)();

some_other_functionobj.method 都是从全局空间调用的,因为它们在 || 中被计算为表达式。条件块。该表达式实际上只是window 对象上的一个属性,这就是调用它的原因。起初我也对此感到困惑,非常有趣的问题,感谢昆汀的正确答案。

这是一篇很棒的博文,有助于阐明 JavaScript 中的 thishttp://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/

已编辑:我已更新此帖子以反映正确答案,我原来的答案不正确。

【讨论】:

  • 感谢您的回答,@Travis,但问题实际上仅与 obj.method 有关,其中this 指的是window 对象。正如@Quentin 指出的那样,这是因为我的逻辑 OR 操作将methodobj 中取出(见他的回答)所以this 关键字实际上是窗口。
  • 这表明即使是认为自己对this有很好理解的人(我)仍然会感到困惑:)
  • 我以为我也这样做了,别担心;)
【解决方案3】:

obj.method() 是语法糖

method.call(obj)

也称为方法调用(不同于调用函数)。如果以任何其他方式使用属性 (method),它会返回一个函数值。例如。在二元运算中使用它,例如

(obj.method || some_other_function)()

使它成为一个函数值,上面的表达式是

的语法糖
(obj.method || some_other_function).call(this)

this 是当前上下文,而不是 obj

(obj.method)() 仍然是一个方法调用,因为 (expression)expression 被视为平等

【讨论】:

  • 谢谢,确实我没有注意到我的|| 正在创建一个隐式变量,而且我也没有意识到你可以将一个方法变成一个函数,(我几乎只使用隔离东西的范围,仅此而已),这个问题对我帮助很大!
  • 真棒编辑,我才刚刚开始使用所有这些 callbindapply ... 属性,我现在非常了解 call !现在我清楚地知道为什么 thiskeyword 是不同的。这是高级语言的永恒麻烦,你必须了解引擎盖下发生的所有事情,而不是重新发明一切......!
猜你喜欢
  • 2021-01-09
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 2010-09-09
相关资源
最近更新 更多