简体   繁体   English

为什么 await 和 async 是有效的变量名?

[英]Why are await and async valid variable names?

I was experimenting with how / is interpreted when around different keywords and operators, and found that the following syntax is perfectly legal:我正在试验围绕不同的关键字和运算符时/的解释方式,发现以下语法是完全合法的:

 // awaiting something that isn't a Promise is fine, it's just strange to do: const foo = await /barbaz/ myFn()

Error:错误:

Uncaught ReferenceError: await is not defined未捕获的 ReferenceError:等待未定义

It looks like it tries to parse the await as a variable name ..?看起来它试图将await解析为变量名..? I was expecting我在期待

await is only valid in async function await 只在 async 函数中有效

or maybe something like或者类似的东西

Unexpected token await意外的令牌等待

To my horror, you can even assign things to it:令我恐惧的是,你甚至可以给它赋值:

 const await = 'Wait, this actually works?'; console.log(await);

Shouldn't something so obviously wrong cause a syntax error, as it does with let , finally , break , etc?如此明显的错误不应该导致语法错误,就像letfinallybreak等一样吗? Why is this allowed, and what the heck is going on in the first snippet?为什么允许这样做,第一个片段中到底发生了什么?

Reserved keywords cannot be used as identifiers (variable names) .保留关键字不能用作标识符(变量名) Unlike most other special Javascript words (like those listed in the question, let , finally , ...), await is not a reserved keyword, so using it as a variable name does not throw a SyntaxError.与大多数其他特殊 Javascript 词(如问题中列出的那些, letfinally 、...)不同, await不是保留关键字,因此将它用作变量名不会引发 SyntaxError。 Why wasn't it made into a reserved keyword when the new syntax came out?为什么新语法出来的时候没有把它做成保留关键字呢?

Backwards compatibility向后兼容性

Back in 2011, when ES5 was still a relatively new thing, code that used await (and async ) as variable names was perfectly valid, so you may have seen something like this on a couple sites:回到 2011 年,当 ES5 还是一个相对较新的东西时,使用await (和async )作为变量名的代码是完全有效的,所以你可能在几个网站上看到过这样的东西:

function timeout(ms) {
  var await = $.Deferred();
  setTimeout(await.resolve, ms);
  return await.promise();
};

The choice of that variable name may seem odd, but there was nothing wrong with it.该变量名称的选择可能看起来很奇怪,但它没有任何问题 await and async have never been reserved keywords - if the writers of the ES2017 specification made await into a reserved keyword, and browsers implemented that change, people visiting those older sites on newer browsers would not be able to use those sites; awaitasync从来都不是保留关键字——如果 ES2017 规范的作者将await变成保留关键字,并且浏览器实现了这一更改,那么在较新浏览器上访问这些旧站点的人将无法使用这些站点; they would likely be broken.他们可能会被打破。

So perhaps if they were made into reserved keywords, a few sites which chose a peculiar variable name wouldn't work properly - why should the existence of those sites permanently affect the future evolution of ECMAscript and result in confusing code like in the question?因此,也许如果将它们制成保留关键字,那么一些选择特殊变量名的站点将无法正常工作——为什么这些站点的存在会永久影响 ECMAscript 的未来发展并导致像问题中那样混乱的代码?

Because browsers will refuse to implement a feature which breaks existing sites.因为浏览器将拒绝实现破坏现有站点的功能。 If a user finds that a site does not work on one browser, but works on another, that will incentivize them to switch browsers - the maker of the first browser would not want that, because that would mean less market share for them, even if it's a feature which makes the language more consistent and understandable.如果一个用户发现一个网站不能在一个浏览器上工作,但在另一个浏览器上工作,这将激励他们切换浏览器——第一个浏览器的制造商不会希望这样,因为这意味着他们的市场份额会减少,即使这是一种使语言更加一致和易于理解的功能。 In addition, the editors of the specification do not want to add something that will never be implemented (or will only be implemented sporadically), because then the specification would lose some of its status as a standard - contrary to its main goal.此外,规范的编辑者不想添加永远不会实施(或只会偶尔实施)的内容,因为那样规范将失去其作为标准的某些地位——这与其主要目标背道而驰。

You could see these interactions in action with Array.prototype.flatten and Array.prototype.contains - when browsers started shipping them, it was found that they broke a few existing sites due to name conflicts, so the browsers backed out of the implementation, and the specification had to be tweaked (the methods were renamed to .flat and .includes ).你可以看到这些与Array.prototype.flattenArray.prototype.contains的交互——当浏览器开始发布它们时,发现它们由于名称冲突而破坏了一些现有站点,因此浏览器退出了实现,并且必须调整规范(方法重命名为.flat.includes )。


There actually is a situation in which await cannot be used as an identifier, which is inside of ES6 modules:实际上一种情况是await不能用作标识符,这是在 ES6 模块内部:

 <script type="module"> const await = 'Does it work?'; </script>

This is because while ES6 (ES2015) modules were being figured out, async / await was already on the horizon ( initial commit for the async / await proposal can be seen at the beginning of 2014), so while designing modules, await could be made a reserved keyword in preparation for the future, without breaking any existing sites.这是因为在设计 ES6 (ES2015) 模块时, async / await已经出现( async / await提案的初始提交可以在 2014 年初看到),因此在设计模块时,可以进行await为将来做准备的保留关键字,不会破坏任何现有站点。


With regards to the first snippet in the question:关于问题中的第一个片段:

 const foo = await /barbaz/ myFn()

This is syntactically valid because await is a valid variable name outside of async functions, and the interpreter thinks you're trying to divide , rather than use a regular expression:这在语法上是有效的,因为awaitasync函数之外的有效变量名,并且解释器认为您正在尝试divide ,而不是使用正则表达式:

const foo = await / barbaz / myFn()

Not relying on Automatic Semicolon Insertion would have identified the problem earlier, because the last / could not have been interpreted as division:不依赖自动分号插入会更早地发现问题,因为最后一个/不能被解释为除法:

 const foo = await /barbaz/; myFn();

This exact somewhat-ambiguous situation was actually specifically brought up in a TC39 meeting on async / await :这种有点模棱两可的情况实际上是在TC39 会议上关于async / await的专门提出的:

YK: What are you worried about? YK:你在担心什么?

WH: Ambiguities on code sequences that start with await/ and then get interpreted in diverging ways (due to the await-as-identifier vs await-as-operator distinction that flips the / between division and starting a regexp) by cover grammars vs. real grammars. WH:以 await/ 开头然后以不同方式解释的代码序列的歧义(由于 await-as-identifier 与 await-as-operator 的区别在除法和开始正则表达式之间翻转 / )通过覆盖语法 vs.真正的语法。 It's a potential bug farm.这是一个潜在的错误农场。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM