为什么等待和异步有效变量名称? [英] Why are await and async valid variable names?

查看:112
本文介绍了为什么等待和异步有效变量名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在不同的关键字和运算符周围解释 / 的方式,并发现以下语法完全合法:

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()

错误:


未捕获的ReferenceError:await未定义

Uncaught ReferenceError: await is not defined

看起来像它尝试将 await 解析为变量名称 ..?我期待

It looks like it tries to parse the await as a variable name..? I was expecting


await仅在异步函数中有效

await is only valid in async function

或类似


意外的令牌等待

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? Why is this allowed, and what the heck is going on in the first snippet?

推荐答案

保留的关键字不能用作标识符(变量名称)。不像大多数其他特殊的Javascript单词(如问题中列出的那些,最后,...), await 保留关键字,因此将其用作变量名称不会抛出SyntaxError。当新语法出现时,为什么不将它变成保留关键字?

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. Why wasn't it made into a reserved keyword when the new syntax came out?

返回在2011年,当ES5仍然是一个相对较新的东西时,使用等待(以及 async )作为变量名称的代码是完全有效,所以你可能在几个网站上看到过这样的东西:

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:

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

该变量名称的选择可能看起来很奇怪,但没有任何错误有了它。 await async 从未被保留的关键字 - 如果ES2017规范的编写者等待成为保留关键字,并且实施了更改的浏览器,访问新浏览器上的旧网站的人将无法使用这些网站;他们可能会被打破。

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; they would likely be broken.

因此,如果他们被制作成保留关键字,那么选择一个特殊变量名的少数网站就不会正常工作 - 为什么这些网站的存在会永久影响ECMAscript的未来发展并导致问题中的代码混乱?

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?

因为浏览器会拒绝实现破坏现有网站的功能。如果用户发现某个网站不能在一个浏览器上运行,但在另一个浏览器上工作,则会激励他们切换浏览器 - 第一个浏览器的制造商不希望这样,因为这意味着他们的市场份额会减少,即使这是一种使语言更加一致和易懂的特征。此外,规范的编辑不希望添加一些永远不会实现的东西(或者只会偶尔实现),因为规范会失去一些标准 - 与其主要目标相反。

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.

您可以通过查看这些互动情况 Array.prototype.flatten Array.prototype.contains - 当浏览器开始发货时,发现由于名称冲突,他们打破了一些现有网站,因此浏览器支持在实现之外,必须调整规范(方法被重命名为 .flat .includes )。

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).

实际上 的情况是等待不能用作标识符,这是ES6模块内部:

There actually is a situation in which await cannot be used as an identifier, which is inside of ES6 modules:

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

这是因为当ES6(ES2015)模块被计算出来时, async / await 已经出现了(初步提交 async / 等待提案可以在2014年初看到),因此在设计模块时,可以制作 await 保留关键字以备将来使用,不会破坏任何现有网站。

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.

关于问题中的第一个片段:

With regards to the first snippet in the question:

const foo = await /barbaz/
myFn()

这在语法上是有效的因为等待 async 函数之外的有效变量名,并且解释器认为你正在尝试,而不是使用正则表达式:

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:

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();

这个确切有点模棱两可的情况实际上是在 TC39会议 async / 等待

This exact somewhat-ambiguous situation was actually specifically brought up in a TC39 meeting on async/await:


YK:您在担心什么?

WH:以await /开头的代码序列的歧义然后以不同的方式解释(由于await-as-identifier与await-as-operator的区别,它会翻转/在div之间并启动regexp通过封面语法与真实语法。这是一个潜在的错误农场。

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. It's a potential bug farm.

这篇关于为什么等待和异步有效变量名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆