我正在尝试如何 /
当围绕不同的关键字和运算符进行解释时,发现以下语法完全合法:
// awaiting something that isn't a Promise is fine, it's just strange to do:
const foo = await /barbaz/
myFn()
错误:
Uncaught ReferenceError: await is not defined
看起来它试图解析
await
作为变量名..?我期待await is only valid in async function
或者类似的东西
Unexpected token await
令我恐惧的是,你甚至可以给它分配东西:
const await = 'Wait, this actually works?';
console.log(await);
如此明显的错误不应该像
let
那样导致语法错误吗? , finally
, break
, ETC?为什么允许这样做,以及第一个片段中到底发生了什么?
最佳答案
保留关键字不能用作 identifiers (variable names) 。与大多数其他特殊的 Javascript 单词(如问题中列出的 let
、 finally
、...)不同,await
不是保留关键字,因此将其用作变量名不会引发 SyntaxError。为什么新语法出来的时候不把它变成保留关键字?
向后兼容性
早在 2011 年,当 ES5 还是一个相对较新的东西时,使用 await
(和 async
)作为变量名的代码是完全有效的,所以你可能在几个网站上看到过这样的东西:
function timeout(ms) {
var await = $.Deferred();
setTimeout(await.resolve, ms);
return await.promise();
};
该变量名称的选择可能看起来很奇怪,但它并没有错。 await
和 async
从来都不是保留关键字——如果 ES2017 规范的编写者将 await
设置为保留关键字,并且浏览器实现了该更改,那么在较新的浏览器上访问这些旧站点的人将无法使用这些站点;他们很可能会被打破。因此,也许如果将它们设为保留关键字,一些选择特殊变量名的站点将无法正常工作 - 为什么这些站点的存在会永久影响 ECMAscript 的 future 发展并导致问题中的代码困惑?
因为浏览器将拒绝实现破坏现有网站的功能。 如果用户发现一个站点不能在一个浏览器上运行,但在另一个浏览器上运行,这将激励他们切换浏览器 - 第一个浏览器的制造商不会想要这样,因为这意味着他们的市场份额减少,甚至如果它是使语言更加一致和易于理解的功能。此外,规范的编辑者不想添加一些永远不会实现(或只会偶尔实现)的东西,因为那样规范将失去其作为标准的一些地位——与其主要目标相反。
您可以看到这些与
Array.prototype.flatten
和 Array.prototype.contains
的交互作用——当浏览器开始发布它们时,发现它们由于名称冲突而破坏了一些现有站点,因此浏览器退出了实现,并且必须调整规范(这些方法被重命名为 .flat
和 .includes
)。实际上有一种情况是
await
不能作为标识符,在 ES6 模块内部:<script type="module">
const await = 'Does it work?';
</script>
这是因为在设计 ES6 (ES2015) 模块时,
async
/await
已经出现(initial commit for the async
/ await
proposal 可以在 2014 年初看到),因此在设计模块时,可以将 await
作为保留关键字,为 future ,而不会破坏任何现有网站。关于问题中的第一个片段:
const foo = await /barbaz/
myFn()
这在语法上是有效的,因为
await
是 async
函数之外的有效变量名,并且解释器认为您正在尝试除法,而不是使用正则表达式:const foo = await / barbaz / myFn()
不依赖自动分号插入会更早发现问题,因为最后一个 /
不能被解释为除法:const foo = await /barbaz/;
myFn();
这种确切的有点模棱两可的情况实际上是在
async
/await
上的 TC39 meeting 中特别提出的:YK: What are you worried about?
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.
关于javascript - 为什么等待和异步有效的变量名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55934490/