Javascript let-in回调函数的范围,需要理解

Javascript let-in回调函数的范围,需要理解,javascript,Javascript,我正在尝试一个回调函数 函数doAsyncTask(cb){ cb(); } doAsyncTask(()=>{ 控制台日志(消息); }) 让message='Callback message'在第一个代码段doAsyncTask的声明前面调用message。 在第二个代码段中,您使用setTimeout()调用cb()cb将在所有代码的末尾调用。因此,第二个示例中的消息在cb()之前声明 第一个片段与下面相同 console.log(message); let message = 'Cal

我正在尝试一个回调函数

函数doAsyncTask(cb){
cb();
}
doAsyncTask(()=>{
控制台日志(消息);
})

让message='Callback message'
在第一个代码段
doAsyncTask
的声明前面调用
message

在第二个代码段中,您使用
setTimeout()
调用
cb()
cb
将在所有代码的末尾调用。因此,第二个示例中的
消息
cb()
之前声明

第一个片段与下面相同

console.log(message);
let message = 'Callback Message'
let message = 'Callback Message'
console.log(message);
第二个片段与下面相同

console.log(message);
let message = 'Callback Message'
let message = 'Callback Message'
console.log(message);

这只是因为执行顺序:

function doAsyncTask(cb) {
  setTimeout(() => cb())
}
doAsyncTask(() => console.log(message))

console.log("message is undefined")
let message = 'Callback Message'
console.log(`message has been initialized to ${message}`)
产出:

message is undefined
message has been initialized to Callback Message
Callback Message
undefined
message is undefined
message has been initialized to Callback Message
而在您的第一个代码中,由于您直接调用
cb()
,设置
消息的行尚未执行:

function doAsyncTask(cb) {
  cb();
}
doAsyncTask(() => console.log(message))

console.log("message is undefined")
let message = 'Callback Message'
console.log(`message has been initialized to ${message}`)
产出:

message is undefined
message has been initialized to Callback Message
Callback Message
undefined
message is undefined
message has been initialized to Callback Message
解释 你遇到的东西可以找到

setTimeout
,简单地说,基本上是将回调函数的执行延迟到执行的“下一个刻度”

基本上,执行上下文被解析并排队。当浏览器执行任何
setTimeout
时,浏览器将其回调排队到执行队列的末尾

请参阅下面的代码以了解更多信息

使用
setTimeout
console.log('Queue',1','timeout'函数已定义');
超时=功能(cb){
log('Queue',3','timeout'函数被执行');
设置超时(cb,0);
}
log('Queue',2','timeout'函数被调用');
超时(函数(){
log('Queue',5','timeout',执行回调');
console.log(消息)
});
log('Queue',4','message'变量已定义');

让消息='确定'这与事件循环的工作方式有关,
setTimeout()
执行被添加到调用的内容中,js引擎继续执行

这是一个数据结构,它知道某个函数应该在某个事件后触发。一旦该事件发生(超时、单击、鼠标移动),它将发送一个通知

事件表
不执行函数,它只是将该函数保留到事件发生之前(本例中为超时),事件发生后,该函数将被放入
事件队列

在您的情况下,
事件队列
将在事件(超时)发生之前具有以下语句
let message='Callback message'

因此,堆栈(也称为调用堆栈和后进先出btw)将包含以下执行顺序:

  • let message='Callback message'
  • ()=>{cb();}

  • 第一条语句将在窗口对象中创建一个全局变量/属性,然后回调将打印
    消息的值,该值是窗口对象中的一个属性。

    这是一个事件循环概念……这是Philip Roberts对事件循环的最精彩阐述。我想这会消除你所有的疑虑。