web-dev-qa-db-ja.com

なぜawaitおよびasyncは有効な変数名ですか?

/は、さまざまなキーワードと演算子の周囲で解釈され、次の構文が完全に合法であることがわかりました。

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

エラー:

キャッチされていないReferenceError:awaitが定義されていません

await変数名 ..?として解析しようとしているようです。私は期待していました

awaitは非同期関数でのみ有効です

または多分何か

予期しないトークンが待機しています

恐ろしいことに、それに物事を割り当てることもできます。

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

letfinallybreakなどの場合のように、明らかに間違ったものは構文エラーの原因になりませんか?なぜこれが許可され、最初のスニペットで一体何が起こっているのですか?

39

予約済みキーワードは 識別子(変数名) として使用できません。他のほとんどの特別なJavascript単語(質問にリストされているようなletfinally、...)とは異なり、awaitではありません予約済みキーワードなので、変数名として使用してもSyntaxErrorはスローされません。新しい構文が出てきたのに、なぜそれが予約キーワードにされなかったのですか?

下位互換性

2011年にES5がまだ比較的新しいものであったときに、変数名としてawait(およびasync)を使用したコードは完全に有効だったので、いくつかのサイトでこのようなものを見たかもしれません:

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

その変数名の選択は奇妙に思えるかもしれませんが、それには間違ったはありませんでした。 awaitasyncが予約済みのキーワードになったことはありません-ES2017仕様の作成者がawaitを予約済みのキーワードにして、ブラウザーがその変更を実装した場合、新しいブラウザはこれらのサイトを使用できません。それらはおそらく壊れます。

したがって、予約済みのキーワードにした場合、特異な変数名を選択したfewサイトは適切に機能しません。これらのサイトの存在が、 ECMAscriptを使用すると、質問のようにコードが混乱しますか?

ブラウザは既存のサイトを破壊する機能の実装を拒否するためです。サイトが1つのブラウザでは機能しないが別のブラウザでは機能することが判明した場合、これは、ブラウザを切り替えることを奨励します-最初のブラウザのメーカーはそれを望まないでしょう。それは、言語をより一貫して理解しやすくする機能であっても、市場シェアが減少することを意味します。さらに、仕様の編集者は、決して実装されない(または散発的にのみ実装される)ものを追加することを望まないでしょう。仕様が標準としてのステータスの一部を失うことになるためです。

Array.prototype.flatten および Array.prototype.contains -ブラウザが出荷を開始したときに、名前の競合のためにいくつかの既存のサイトが破損していることが判明したため、ブラウザは実装から取り消され、仕様を微調整する必要がありました(メソッドの名前は-に変更されました- .flat および .includes )。


実際にはですawaitを識別子として使用できない状況があり、これはES6モジュール内にあります。

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

これは、ES6(ES2015)モジュールが把握されていた間に、async/awaitがすでに地平線上にあったためです( async/awaitプロポーザル は2014年の初めに見ることができます)。したがって、モジュールの設計中に、既存のサイトを壊すことなく、awaitを将来に備えて予約キーワードにすることができます。


質問の最初のスニペットに関して:

const foo = await /barbaz/
myFn()

awaitasync関数の外では有効な変数名であり、インタプリタはdivideではなく、正規表現を使用するより:

const foo = await / barbaz / myFn()

セミコロンの自動挿入に依存しない場合は、最後の/は除算として解釈できませんでした:

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

この正確なややあいまいな状況は、実際にasync/awaitの-​​ TC39ミーティング で具体的に取り上げられました。

YK:何が心配ですか?

WH:await /で始まり、その後、異なる方法で解釈されるコードシーケンスのあいまいさ(await-as-identifierとawait-as-が原因で)除算と正規表現の開始の間の/を反転する演算子の区別)カバー文法と実際の文法の比較。それは潜在的なバグファームです。

66