var let 可以,但让 let 不是?



//Version A:
var let = true;
console.log(let);//true
//Version B:
let let = 0; //syntax Error: let is disallowed as a lexically bound name
console.log(let);

是否有任何特殊原因,我们允许使用var而不是let创建名称let变量?通过这个实验,这是否也意味着变量名let可以存在于全局级别,但不能存在于某个范围级别?但是,全球不考虑范围吗?

正如您所猜测的,这是由于向后兼容性。const一直是一个保留字(在 ES5 规范中称为FutureReservedWord)。自从 JavaScript 开始以来,你从来没有能够命名一个变量const

let也被认为是FutureReservedWord,但只是在严格模式下- 但严格模式仅在ES5中引入,当时ES6在遥远的地平线上。

'use strict';
let = 10; // errors

var一直存在,因此一直禁止将变量命名为var

变量从来不能被命名为const,但是let没有这样的限制。如果在(非严格的)ES5或ES6中禁止它,它将破坏向后兼容性,Web标准不惜一切代价努力不破坏。

如果当JS首次被设计出来时,人们有先见之明会想:"也许,在未来,我们会想要使用constlet这两个词来声明变量,所以我们现在将它们作为保留关键字。 然后你就不会看到不一致,因为两者都从一开始就被保留了。

有许多类似的关键字有时在现代JS中具有特殊含义,但在用作变量名时不会引发错误。

static = 5;
async = 10;
await = 15;
yield = 20;
console.log('finished without errors');

因为规范是这么说的。

从 https://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations-static-semantics-early-errors:

13.3.1 Let 和 Const 声明

13.3.1.1 静态语义:早期错误

LexicalDeclaration:LetOrConstBindingList;

  • 如果BindingList的 BoundNames 包含"let",则为语法错误。

变量语句规范没有这样的限制,可能是因为在定义varlet未使用,更改var规范将是一项重大更改。

constlet是最近添加到 JS 中的,但在它们被添加之前很长一段时间const是一个保留关键字(大概是基于它被认为是未来可能添加到该语言的基础)。

由于let曾经是一个有效的变量名,这可能是为了向后兼容。

constlet在ECMA2011中作为未来保留字引入。

ECMA2011 - 引入constlet作为未来保留字

7.6.1.2 未来保留字

以下单词在建议的扩展中用作关键字,并且 因此保留,以允许将来采用的可能性 的扩展。

未来保留字 ::

  • .class
  • 枚举
  • 延伸
  • 常量
  • 出口
  • 进口

当以下标记出现在严格模式代码中时,它们也被视为FutureReservedWords(请参阅 10.1.1)。发生次数 在任何上下文中的严格模式代码中的任何这些令牌 出现FutureReservedWord将产生错误必须 还会产生等效错误:

  • 实现
  • 私人
  • 公共
  • 屈服
  • 接口
  • 保护
  • 静态的

ECMA2012 - 批准的关键字

后来在ECMA2012这两个词都被添加为关键字,这些关键字不能用作标识符

7.6.1.1 关键字

以下标记是 ECMAScript 关键字,不能用作 ECMAScript 程序中的标识符

关键词::

  • 删除
  • 进口
  • 抓住
  • 实例
  • 尝试
  • .class
  • 出口
  • 类型
  • 类型
  • 继续
  • 最后
  • 新增功能
  • 变量
  • 常量
  • 返回
  • 无效
  • 调试器
  • 功能
  • 违约
  • 如果
  • 开关

虽然用作标识符const在每个模式下都会抛出错误,let只会在严格模式下抛出错误,现在使用您的示例仍然如此:

有效

在没有严格模式的情况下使用let作为标识符。

(function(){
//REM: Works
var let = 5;
console.log(let);
})();

无效

使用const作为标识符而不使用严格模式。

(function(){
//REM: Throws an error
var const = 5;
console.log(const);
})();

在严格模式下使用letconst作为标识符。

(function(){
'use strict';
//REM: Throws an error
var let = 5;
console.log(let);
})();

(function(){
'use strict';
//REM: Throws an error
var const = 5;
console.log(const);
})();

因此,从历史上看,ECMA对关键字const的严格程度比从一开始就let严格。虽然自ECMA2012以来let可能不会用作标识符,但我认为由于向后兼容性,它被忽略了。

这是最新的letconst规格。

是否有任何特殊原因允许使用 var 创建名称为 let 但不允许的变量?

为了向后兼容,var允许这样做。

let声明在ES2015标准之前不存在,因此let可以自由地用作变量名。更改语言以停止允许该变量名称可能会破坏在 ES2015 存在之前编写的应用程序,当时let是一个非常好的变量名称。(涵盖了二十年的时间 - 1995年至2015年!

由于let是一项新功能,因此没有要破坏的现有代码,并且不允许将let作为变量名称可以避免语法混淆的潜在来源。

最新更新