【问题标题】:Lexical this in JavaScriptJavaScript 中的 this 词法
【发布时间】:2018-03-06 23:09:27
【问题描述】:

我刚刚阅读了 You Don't Know Javascript 系列的“范围和闭包”一书。这本书有一个附录谈论这个词汇。它给出了 this 如何失去其绑定以及如何使用箭头函数解决的示例。

我对第一种情况的示例有疑问。这是本书的例子:

var obj = { id: 2, cool: function(){console.log(this.id)}}
id=3;
obj.cool();
setTimeout(obj.cool, 100);

这可以很好地打印预期结果:第一次为 2,在 setTimeout 调用中为 3。

但如果我通过以下方式更改此调用:

var obj = { id: 2, cool: function(){console.log(this.id)}}
id=3;
obj.cool();
setTimeout(function(){obj.cool()}, 100); 

两次都打印 2。

我的猜测是,通过将对 obj.cool 的调用包含在一个函数中,我正在创建一个 id 具有预期值的范围。

我说的对吗?这是正确的解释吗?我错过了什么吗?

【问题讨论】:

  • 不,您没有创建一个带有额外 id 的范围。您现在只需在新函数中调用obj 上的obj.cool
  • 您能否进一步解释为什么23 是第一个示例中的预期结果?我想您对此的理解也存在一些缺陷。
  • @Bergi 你可以在这里找到解释:github.com/getify/You-Dont-Know-JS/blob/master/…
  • obj.cool(); 使用obj 的上下文调用cool 函数。 obj.cool 仅将函数传递给 setTimeout,而没有 obj 的上下文。当它被调用时,它不再与obj 关联,它只是一个普通函数,因此它不知道将obj 用作this

标签: javascript this lexical-scope


【解决方案1】:

不完全是。在第一个示例中,setTimeout 调用您的 cool 函数不是作为方法,而是作为简单函数。这就是为什么你“继承”一个“全局”作用域并且id 等于 3。

如果您使用 . 表示法调用函数,就像在第二个示例中一样 - 您的调用范围是您在 . 之前放置的任何内容,并且因为 obj.id === 2 - 您会看到 2 打印。

理解这一点的关键是:setTimeout 仅获得对函数的引用。它不知道您的函数是对象的方法。它也不知道关于这个对象的任何事情。它所得到的只是对“要执行的代码”的引用。在第二种情况下,您明确告诉解释器您要执行函数cool 作为对象obj 的方法。

【讨论】:

  • 我认为你是对的。这与@rocky-sims 在评论中给出的解释相同,这对我来说很有意义。谢谢!
  • 附带说明,您还可以使用Function.prototype.bind 创建一个新函数,该函数将this 绑定到obj,而不是使用匿名函数调用该方法:setTimeout(obj.cool.bind(obj), 100);bind也可以用来创建partially applied functions
猜你喜欢
  • 1970-01-01
  • 2011-04-01
  • 2012-06-30
  • 2015-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多