为何异步IIFE中可调用后声明的箭头函数,外部调用却报错?
为什么调用
settingsDataAvailable的时机不同会导致引用错误? 咱们把两种场景的核心差异拆解开来,就能明白为啥一个正常运行、一个报错了:
第一个场景(正常执行)
先看你能正常运行的代码:
(async () => { const brwSettings = await brwApi.get( ajax_var.resturl + "?_wpnonce=" + ajax_var.restnonce ); settingsDataAvailable(brwSettings); })(); const settingsDataAvailable = (data) => { console(data); };
这里的关键是异步函数的执行顺序:
- 异步IIFE启动后,遇到
await brwApi.get(...)会暂停执行,把控制权交回主线程。 - 主线程继续往下执行,完成
const settingsDataAvailable的声明和初始化,这个箭头函数就被正式定义好了。 - 等
brwApi.get的异步请求完成后,异步IIFE才会恢复执行,这时候调用settingsDataAvailable,它已经处于可用状态,自然不会报错。
第二个场景(抛出引用错误)
再看报错的代码:
(async () => { const brwSettings = await brwApi.get( ajax_var.resturl + "?_wpnonce=" + ajax_var.restnonce ); })(); settingsDataAvailable(brwSettings); // 抛出错误 const settingsDataAvailable = (data) => { console(data); };
问题出在同步执行顺序和const的「暂时性死区(TDZ)」:
- 异步IIFE启动后同样遇到
await暂停,交还控制权给主线程。 - 但主线程接下来直接执行
settingsDataAvailable(brwSettings)——这时候const settingsDataAvailable的声明语句还没被执行到。虽然const声明的变量会被提升,但在声明语句执行前,变量处于「暂时性死区」,完全无法访问,所以直接抛出Uncaught ReferenceError。 - 另外补充:哪怕忽略
brwSettings是IIFE内部局部变量导致的未定义问题,光是调用settingsDataAvailable的时机,就已经踩了TDZ的坑。
顺便提一句:const和let声明的变量都有暂时性死区,只有在声明语句执行后,变量才能被正常访问;而var因为没有TDZ,提升时会被初始化为undefined,但咱们用const就得遵守这个规则。
内容的提问来源于stack exchange,提问作者RowanBlub
相关产品推荐
相关产品推荐

