使用 'let' 作为变量名不会在 google v8 中引发任何错误

Using 'let' as a variable name is not throwing any errors in google v8

我在 chrome 开发人员控制台中编写了一些随机代码。令我惊讶的是,chrome 让我使用 let 作为变量名,这是完全错误的,因为 let 是保留关键字。我需要了解为什么会这样。

场景:

var const = 78 //throws an error as expected

var function = 46 //throws an error as expected

var let = 56 //didn't throw an error :O

let //prints 56, which is wrong because 'let' is a keyword

let ab = 90

ab //prints 90 as expected

node 中存在此缺陷。但是,当我在 Babel REPL 中尝试时,它会抛出一个错误。

我认为这与 Google v8

有关

出于兼容性原因,仅在严格模式下禁止使用保留的 ES6 关键字。

Babel(通过 strict mode plugin)默认使用严格模式。在浏览器或 Node 中,您可以通过在文件或函数的开头添加 "use strict"; 来隐式设置严格模式。

运行 如您所料,以下代码片段将在 Chrome 中抛出错误:

"use strict";
var let = 43;
// Throws: Uncaught SyntaxError: Unexpected strict mode reserved word

可以在 this article by Mohsen Azimi 中找到对这背后的推理的很好的描述。这是它的快速摘要。

以下关键字在 JavaScript 规范中定义为 FutureReservedWord:

implements     interface   let       package    private
protected      public      static    yield

在普通模式下,这些都可以作为变量名使用,不会出错;但是,在严格模式下,它们被视为保留字并会抛出以下错误:

SyntaxError: Cannot use the reserved word 'let' as a variable name in strict mode.

这样 ES2015 之前的代码就不会被破坏——如果有人在遗留应用程序中命名了很多变量 let,如果 JS 规范突然破坏了一切,他们可能会不高兴.

这是语言成长的乐趣。

简而言之,const在ECMAScript 1st Edition中被列为“future reserved word”,这意味着虽然它(当时)没有任何意义,但不能使用对于标识符。 (当然,function 一直是保留字。)但是 let 既不是保留字也不是未来的保留字,因此它可以用于标识符(并且曾经是)。直到第 5 版才将 let 确定为未来的保留字,然后才在新的严格模式 ES5 中加入。 (你的例子在严格模式下不起作用。)由于 let 没有被保留,它可能被广泛使用在代码中,并且不能追溯地在 ES2015 中成为一个纯粹的保留字。因此,它仍然是一个有效的标识符(在松散模式下)。解析器必须根据上下文确定它是声明还是标识符。 (这有一个有趣的结果,在松散模式下,忘记在 let 之后键入标识符不是语法错误,let = 42; 工作得很好——即使 let 没有在任何地方声明[感谢我所说的 The Horror of Implicit Globals]。这些是始终使用严格模式的充分理由 [因为 let 不能成为严格模式下的标识符,而且严格模式没有隐式全局变量]。 )

JavaScript 也有 contextual 保留字。 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 之前不存在,因此不可能存在使用 await 作为标识符的 async 函数。同样,yield 只是生成器函数中的保留字。