异步操作的闭包



我有几个关于闭包的问题。很抱歉,如果这似乎只是另一个结束问题,有很多帖子和文章,我读了很多,但我仍然有问题,找不到答案。

var message = 'Hello!';
document.getElementById('foo').onclick = function(){alert(message)};
message = 'Goodbye!';

这里会提醒"再见",解释是:"闭包不仅仅传递变量的值,甚至是对变量的引用。闭包捕获变量本身!">

a。请,有人能向我解释一下"捕获变量本身"是什么意思吗?这是如何使信息变成"再见"而不是"你好"的?

b。功能还是警报是关闭?

c。此外,我对以下内容是否正确:onclick被添加到事件表中,它向事件队列发送通知(当单击发生时),事件循环检查调用堆栈,它为空,因此正在添加和执行警报消息。在这一切发生的同时,JS引擎已经到达了代码行->message='Goodbye!';这就是为什么"再见"最终会被提醒?!

for (var i = 1; i < 5; i++) {
setTimeout(() => console.log(i), i*1000)
}
vs 
for (let i = 1; i < 5; i++) {
setTimeout(() => console.log(i), i*1000)
}
for (var i = 1; i < 5; i++) {
(function(i){
setTimeout(() => console.log(i), i*1000)
})(i)
}
  • 我总是读到"当第一个setTimeout()运行时,我已经是5了,我们没有任何方法引用它"——但当第一个setTimeout()运行时,循环已经完成的原因是什么?这实际上与事件队列等有关吗
  • 我也经常读到问题是变量I没有被引用。我只是不明白引用变量I和循环结束后运行的setTimeout有什么关系
  • 当我使用let而不是var时,我总是用let读取它的块范围,而不是函数范围,这样我就不会变成全局的。我理解。但有人能解释一下,到底发生了什么?为什么/为什么我不是负责setTimeout的全局变量,在循环完成后没有被调用?我不明白其中的联系
  • 另外,请有人解释一下为什么用i*1000,我不会像我所理解的那样总是5?是因为它在封闭之外吗

非常感谢,如果有什么不清楚的地方,请告诉我。

请有人向我解释"捕获变量本身"的含义,以及这是如何使消息变成"再见"而不是"你好"的

函数只是提醒message变量的值。

当函数运行时,该值为'Goodbye!'

函数或警报是闭包?

该示例中没有闭包。

此外,我对以下内容是否正确:onclick被添加到事件表中,它向事件队列发送通知(当单击发生时),事件循环检查调用堆栈,它为空,因此正在添加和执行警报消息。在这一切发生的同时,JS引擎已经到达了代码行->message='Goodbye!';这就是为什么"再见"最终会被提醒?!

否。

  1. 'Hello!'分配给变量
  2. 您分配事件处理程序
  3. 'Goodbye!'分配给变量
  4. 元素被点击
  5. 事件触发器
  6. 函数被调用

在单击之前,它不会添加到堆栈中,因此不会在步骤2和3之间添加。

我总是读到"当第一个setTimeout()运行时,我已经是5了,我们没有任何方法引用它"-但当第一个setTimeout(?这实际上与事件队列等有关吗?!

setTimeout设置了一个函数以在将来运行,并且不会阻止其他代码运行,因此循环保持运行,并更改i

我也经常读到问题是变量I没有被引用。

这与引用无关。

我只是不明白引用变量I与循环结束后运行的setTimeout有什么关系。

i的关系与setTimeout无关。传递给setTimeout的函数显式使用i。这就是为什么它很重要。

但有人能解释一下,到底发生了什么吗?为什么/为什么我不是负责setTimeout的全局变量,在for循环完成后没有被调用?我不明白其中的联系。

同样,与setTimeout没有任何关系。

每次循环时,都会创建一个新函数并将其传递给setTimeout。该函数使用i

如果i的作用域是块而不是包含函数,那么每次循环时,都会得到一个不同的i变量(而不是使用var或全局函数得到的相同的i变量)。

此外,请有人解释为什么用i*1000,我不会像我所理解的那样总是5?是因为它在封闭之外吗?

否。这是因为它在传递给setTimeout的函数之外,所以它被使用立即用当前,而不是在循环结束后i的值变为任何值之后。

最新更新