保留关键字不能用作标识符(变量名)。与大多数其他特殊的Javascript的话(像那些在这个问题列出let
,finally
...),await
是不是一个保留关键字,所以使用它作为一个变量名不抛出一个SyntaxError。为什么新语法出来的时候不把它做成保留关键字呢?
向后兼容
早在 2011 年,当 ES5 还是一个相对较新的东西时,使用await
(and async
) 作为变量名的代码是完全有效的,所以你可能在几个网站上看到过这样的事情:
function timeout(ms) {
var await = $.Deferred();
setTimeout(await.resolve, ms);
return await.promise();
};
选择那个变量名可能看起来很奇怪,但它并没有错。await
并且async
从来没有被保留关键字——如果 ES2017 规范的作者await
成为保留关键字,并且浏览器实现了这一改变,那么在新浏览器上访问那些旧站点的人将无法使用这些站点;他们很可能会被打破。
因此,也许如果将它们设置为保留关键字,一些选择特殊变量名称的站点将无法正常工作 - 为什么这些站点的存在会永久影响 ECMAscript 的未来演变并导致问题中的代码混乱?
因为浏览器将拒绝实现破坏现有站点的功能。如果用户发现某个网站无法在一个浏览器上运行,但在另一个浏览器上运行,这将激励他们切换浏览器——第一个浏览器的制造商不会想要这样,因为这意味着他们的市场份额会减少,即使这是一个使语言更加一致和易于理解的功能。此外,规范的编辑者不想添加永远不会实现(或只会偶尔实现)的东西,因为那样规范将失去其作为标准的某些地位——与其主要目标背道而驰。
您可以看到这些交互与Array.prototype.flatten
和Array.prototype.contains
- 当浏览器开始发布它们时,发现它们由于名称冲突而破坏了一些现有站点,因此浏览器退出了实现,并且必须调整规范(方法被重命名为.flat
和.includes
)。
实际上有是其中的情况await
不能被用作标识符,这是ES6module内:
<script type="module">
const await = 'Does it work?';
</script>
这是因为当 ES6 (ES2015) module被弄清楚时,async
/await
已经在地平线上(可以在 2014 年初看到/提案的初始提交async
await
),所以在设计module时,await
可以将保留关键字设置为准备为未来,不破坏任何现有的网站。
关于问题中的第一个片段:
const foo = await /barbaz/
myFn()
这在语法上是有效的,因为它await
是async
函数之外的有效变量名,并且解释器认为您正在尝试除,而不是使用正则表达式:
const foo = await / barbaz / myFn()
不依赖于自动分号插入会更早地发现问题,因为最后一个/
不能被解释为除法:
const foo = await /barbaz/;
myFn();
这种有点模棱两可的情况实际上是在/上的TC39 会议中特别提出的:async
await
YK:你担心什么?
WH:以 await/ 开头的代码序列的歧义,然后以不同的方式解释(由于 await-as-identifier 与 await-as-operator 的区别,在除法和开始正则表达式之间翻转 /)覆盖语法 vs.真正的语法。这是一个潜在的错误农场。