在声明所述变量之前立即调用的异步函数中使用的未提升变量(let,const)

Posted

技术标签:

【中文标题】在声明所述变量之前立即调用的异步函数中使用的未提升变量(let,const)【英文标题】:Unhoisted variables (let, const) used in immediately invoked async function before declaration of said variables 【发布时间】:2020-05-31 00:14:48 【问题描述】:

下面的代码应该工作吗?

(async () => 
  await new Promise(r => setTimeout(r, 1000))
  useNum();
)();

let num = 10;
function useNum() 
  return num + 1;

https://jsbin.com/tayotitepa/edit?html,output

ios 上的 Safari (v13.3) 说这是不可能的(num 变量不存在),而 Chrome 和 Firefox 认为这很好。

如果您删除 await new Promise... 行,Chrome 和 Firefox 就会抱怨。

Chrome 和 Firefox 似乎在这里是正确的,因为我们不是 awaiting 立即调用的异步函数,所以当 await new Promise... 行完成时,脚本的其余部分已经完成处理。但我想我会检查一下,因为也许规范说它严格关于变量声明的 ordering 和这些变量的用法,所以它的“时间”无关紧要变量的使用。

【问题讨论】:

我认为这个问题与async/await 无关。 Safari 是错误的。 另外,letconst 被提升;它的工作方式与var 提升不同。 在 High Sierra 的 Safari 上运行良好 【参考方案1】:

我尝试了不同的场景,我观察到的是

    async/await 与此无关。 let num 已提升,但值为 undefined

所以代码看起来像什么

let num; // --- hoisted with value as undefined
setTimeout(() => , 1000)
console.log(useNum());

num = 10; // --- value is assigned here
function useNum(str) 
  return num + 1;

如您所知,java-script 是同步的,即它每次执行每一行 a,所以当我们调用 useNum 方法时,num 将是未定义的。

【讨论】:

您的代码与 OP 不同。应该是setTimeout(() => console.log(useNum(), 1000)

以上是关于在声明所述变量之前立即调用的异步函数中使用的未提升变量(let,const)的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript变量提升与函数提升

js 立即执行函数,() .则前面的function 是表达式,不能是函数申明

变量提升

JavaScript 函数声明,函数表达式,匿名函数的区别,深入理解立即执行函数(function(){…})()

JavaScript基础

JavaScript学习手册(55)