//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首次被设计出来时,人们有先见之明会想:"也许,在未来,我们会想要使用const
和let
这两个词来声明变量,所以我们现在将它们作为保留关键字。 然后你就不会看到不一致,因为两者都从一开始就被保留了。
有许多类似的关键字有时在现代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"
,则为语法错误。
变量语句规范没有这样的限制,可能是因为在定义var
时let
未使用,更改var
规范将是一项重大更改。
const
和let
是最近添加到 JS 中的,但在它们被添加之前很长一段时间const
是一个保留关键字(大概是基于它被认为是未来可能添加到该语言的基础)。
由于let
曾经是一个有效的变量名,这可能是为了向后兼容。
const
和let
在ECMA2011中作为未来保留字引入。
ECMA2011 - 引入const
和let
作为未来保留字
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);
})();
在严格模式下使用let
或const
作为标识符。
(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
可能不会用作标识符,但我认为由于向后兼容性,它被忽略了。
这是最新的let
和const
规格。
是否有任何特殊原因允许使用 var 创建名称为 let 但不允许的变量?
为了向后兼容,var
允许这样做。
let
声明在ES2015标准之前不存在,因此let
可以自由地用作变量名。更改语言以停止允许该变量名称可能会破坏在 ES2015 存在之前编写的应用程序,当时let
是一个非常好的变量名称。(涵盖了二十年的时间 - 1995年至2015年!
由于let
是一项新功能,因此没有要破坏的现有代码,并且不允许将let
作为变量名称可以避免语法混淆的潜在来源。