这是一种不断发展的语言的乐趣。
简短的版本是const
在 ECMAScript 第一版中列为“未来保留字”,这意味着虽然它没有任何意义(当时),但它不能用于标识符。(当然,function
一直是保留字。)但let
既不是保留字也不是未来保留字,因此它可以用于标识符(并且曾经是)。直到第 5 版let
才被确定为未来的保留字,然后才在新的严格模式中添加了 ES5。(您的示例在严格模式下不起作用。)因为let
没有保留,它可能被广泛使用的代码中使用,并且不能在 ES2015 中追溯成为纯粹的保留字。因此,它仍然是一个有效的标识符(在松散模式下)。解析器必须根据上下文确定它是声明还是标识符。(这有一个有趣的结果,在松散模式下,忘记在let
不是语法错误之后输入标识符,let = 42;
工作得很好——即使let
没有在任何地方声明[感谢我称之为隐式全局的恐怖]。这些是总是使用严格模式的好理由[因为let
在严格模式下不能是标识符,而且严格模式没有隐式全局变量]。)
JavaScript 也有上下文保留字。async
是一个有效的标识符(即使在严格模式下,甚至在async
函数内部!),它只在以前它会是标识符语法错误的地方有特殊含义:
// Since `blah function` here is a syntax error:
blah function foo() {
}
// ...no valid code would have an identifier in that position, so it was possible
// to add an `async` modifier:
async function foo() {
}
await
是一个有效的标识符(即使在严格模式下),除非它在async
函数内;那么它是一个保留字。这是可能的,因为async
之前不存在函数await
,因此不可能存在async
用作await
标识符的函数。同样,yield
只是生成器函数内部的保留字。