Node.js控制台初始化变量抛异常后如何复用该变量?
Node.js v12.22.9 REPL中let变量异常问题分析
问题场景
me@my-machine:~/Projects/.../my-projects$ node Welcome to Node.js v12.22.9. Type ".help" for more information. > let foo = (function(){ throw new Error() })() Uncaught Error at REPL1:1:30 > foo Uncaught ReferenceError: foo is not defined > foo = 1 Uncaught ReferenceError: foo is not defined > let foo = 1 Uncaught SyntaxError: Identifier 'foo' has already been declared > let bar undefined > bar = (function(){ throw new Error() })() Uncaught Error at REPL6:1:26 > bar undefined > bar = 1 1 > let bar = 1 Uncaught SyntaxError: Identifier 'bar' has already been declared
现象总结
- 无法获取
foo的值,触发Uncaught ReferenceError: foo is not defined - 无法为
foo赋值,同样触发引用错误 - 尝试重新定义
foo(无论是否带初始值),触发Uncaught SyntaxError: Identifier 'foo' has already been declared foo标识符完全无法复用,直到关闭当前REPL会话;但先声明再赋值的bar无此问题
疑问
这是Bug还是预期行为?能否不重启REPL消除该现象并复用foo?
分析与解答
这是预期行为,完全符合ES6 let的声明规则:
暂时性死区与初始化失败:
let声明变量时,标识符会先被注册到当前作用域,但从声明到初始化完成前,变量处于「暂时性死区」。执行let foo = (function(){ throw new Error() })()时,foo已经被加到REPL的全局作用域,但初始化阶段因抛出异常中断,导致变量从未完成初始化:- 访问
foo时,因未完成初始化仍在死区,触发引用错误 - 再用
let声明,因作用域已存在该标识符,触发重复声明错误
- 访问
bar正常的原因:先执行let bar时,变量已完成初始化(默认值undefined),后续赋值抛出异常仅导致赋值操作失败,变量本身已存在于作用域,因此可正常访问、重新赋值
不重启REPL复用foo的方法
Node.js REPL提供了.clear命令,执行后会清空当前上下文的作用域,之后即可重新声明foo:
> .clear Clearing context... > let foo = 1 undefined > foo 1
内容的提问来源于stack exchange,提问作者Luis Masuelli
相关产品推荐
相关产品推荐

