我刚刚读了"你不知道Javascript"系列的"范围和闭包"一书。这本书有一个附录,谈到了词汇。它给出了一个示例,说明如何丢失其绑定以及如何使用箭头函数解决。
我对第一种情况的例子有问题。这是本书的例子:
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 具有预期值的作用域。
我说的对吗?这是正确的解释吗?我错过了什么吗?
不完全是。在第一个示例中,setTimeout
不是将cool
函数作为方法调用,而是作为简单函数调用。这就是为什么你"继承"了一个"全局"作用域,id
等于 3。
如果您使用.
表示法调用函数,例如在第二个示例中 - 您的调用范围是您在.
之前和自 obj.id === 2
年以来放置的任何内容 - 您会看到打印的 2
理解这一点的关键是:setTimeout
只得到一个函数的引用。它不知道你的函数是一个对象的方法。它对这个对象也一无所知。它得到的只是对"要执行的代码"的引用。在第二种情况下,您明确告诉解释器您希望将函数cool
作为对象obj
的方法执行。