【问题标题】:Using 'let' as a variable name is not throwing any errors in google v8使用“let”作为变量名不会在 google v8 中引发任何错误
【发布时间】:2017-03-27 21:10:50
【问题描述】:

我在 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 有关

【问题讨论】:

  • 为什么不避免使用可能的保留字呢?有“不使用”字的列表和官方的“保留字”
  • 不确定是否可以作为答案发布,但我认为这是为了防止旧代码被破坏。如果 ES2015 之前的应用程序使用了一个名为 'let' 的变量怎么办?
  • 我明白了。如果有官方的“保留词”列表,为什么v8不遵循它。我希望它会引发错误。
  • @PraneshRavi 你也可以var undefined = 10
  • @JoeClay 我一直使用 eslint:P。我只是想知道这背后的原因。感谢您的回答。

标签: javascript node.js google-chrome ecmascript-6 v8


【解决方案1】:

这是不断发展的语言的乐趣。

简短的版本是 const 在 ECMAScript 第一版中被列为“未来的保留字”,这意味着虽然它没有任何意义(当时),但它不能用于标识符。 (当然,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 函数中;那么它是一个保留字。这是可能的,因为在await 之前不存在async 函数,因此不可能存在使用await 作为标识符的async 函数。同样,yield 只是生成器函数中的保留字。

【讨论】:

    【解决方案2】:

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

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

    运行以下代码 sn-p 将在 Chrome 中按预期抛出错误:

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

    【讨论】:

      【解决方案3】:

      可以在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 规范突然破坏了一切,他们可能不会高兴。

      【讨论】:

      • 干净。我仍然建议 v8 人员添加 deprecated 警告以修复旧版应用程序。
      • @PraneshRavi:是的,我一直发现"use strict"; 是解决此类问题的一个笨拙的解决方案,尤其是现在 JS 应用程序往往被拆分为许多单独的文件。跨度>
      • 虽然 Javascript 就是这样,但它并没有被弃用,只是在严格的代码中是不允许的。一旦 ES6 模块落地,大多数新代码都最好使用它们,并且默认情况下它们是严格的,但设置 linting 规则以提醒您在非 ES6 模块中忘记use strict 也相对容易。
      • @loganfsmyth:啊,是的,我忘记了默认使用严格模式的模块。
      猜你喜欢
      • 1970-01-01
      • 2023-02-20
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      相关资源
      最近更新 更多