当为“var”和“let”分配一个抛出错误的函数的返回值时,是什么导致它们之间的不同行为

IT技术 javascript var throw let
2021-03-05 15:11:30

请在下图中找到代码。1. 将实际抛出错误的函数的返回值赋给使用关键字'let'声明的变量'withLet'。2.调用'withLet',出现错误:'withLet is not defined'。3.尝试使用'let'断言'withLet',错误显示'withLet'已经被声明。

但是“var”不存在悖论(请在下图中找到)。

我很好奇是什么导致了这两种情况之间的不同行为。“未定义”和“已经声明”描述了相同的变量,这是非常连贯的。

let withLet = (function() {throw 'error!'})()
var withVar = (function() {throw 'error!'})()
//VM2470:1 Uncaught error!
//(anonymous) @ VM2470:1
//(anonymous) @ VM2470:1
withLet
//VM2484:1 Uncaught ReferenceError: withLet is not defined at 
//<anonymous>:1:1
//(anonymous) @ VM2484:1
withVar
//undefined
let withLet = 'sth'
//VM2520:1 Uncaught SyntaxError: Identifier 'withLet' has already been 
//declared
//at <anonymous>:1:1
//(anonymous) @ VM2520:1
withVar = 'sth'
//"sth"

截屏:

1个回答

var变量声明被提升 - 变量名初始化被提升到包含函数的顶部(或者,如果没有函数,到外部块的顶部)。所以

var withVar = (function() {throw 'error!'})()

被解释器解析为

var withVar;
withVar = (function() {throw 'error!'})()

情况并非如此let-let一旦let __线路运行,变量就会被初始化有赋值时,首先解析右边;如果右侧抛出错误,则它永远不会到达左侧,并且使用letnever声明的变量会被正确初始化;它将永远留在非军事区/临时死区,因此尝试重新分配它会引发错误。

这有点奇怪,因为代码是在控制台中运行的——通常,JS 在<script>标签内运行,如果发生这样的错误,通常不会再运行代码,并且声明的变量let不再可重新分配的事实是最少的担心。


以上是早期 Chrome 版本中的一个问题。但是在 Chrome 80+ 中let现在允许重新声明,所以错误

未捕获的 SyntaxError:标识符“withLet”已被声明

不应再发生,无论先前的变量初始化是否成功:

在此处输入图片说明

只是稍微扩展一下 - 变量具有三个阶段才能成为“真实”。声明(那个标识符存在)、初始化(那个标识符是活动的并且可以使用)、赋值(有一个分配给那个标识符的值)。对于var声明 + 初始化被提升。对于let/const只有声明被提升,初始化稍后进行 - 如上所述,当let myVar到达行时。
2021-05-08 15:11:30