这是一种不断发展的语言的乐趣。
简短的版本是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只是生成器函数内部的保留字。