web-dev-qa-db-ja.com

ES6はすぐに矢印関数を呼び出しました

これはNode.jsコンソール(4.1.1および5.3.0でテスト済み)で機能するのに、ブラウザー(Chromeでテスト済み)では機能しないのはなぜですか?このコードブロックは、Okを記録する匿名関数を作成して呼び出す必要があります。

() => {
  console.log('Ok');
}()

また、上記のworks Nodeでは、これは機能しません:

n => {
  console.log('Ok');
}()

これも:

(n) => {
  console.log('Ok');
}()

奇妙なのは、パラメーターが追加されると、実際にすぐに呼び出す部分でSyntaxErrorがスローされることです。

118
Cristy

あなたは関数定義ではなく関数式にする必要があります名前が必要で、有効なJavaScriptにします。

(() => {
  console.log('Ok');
})()

IIFE と同等です

(function(){
   console.log('Ok')
})();

そして、これがNode.jsでは機能するがchromeでは機能しない理由として考えられるのは、そのパーサーが自己実行関数として解釈するためです。

function() { console.log('hello'); }();

Node.jsで正常に動作します。これは関数式であり、chromeとfirefoxであり、ほとんどのブラウザはこのように解釈します。手動で呼び出す必要があります。

JavaScriptでは関数にステートメントを含めることができないため、パーサーに関数式を予期するように指示する最も広く受け入れられている方法は、単純に関数をラップすることです。この時点で、パーサーはfunctionキーワードを検出すると、それを関数宣言ではなく関数式として解析することを認識します。

パラメータ化されたバージョンに関しては、これは機能します。

((n) => {
  console.log('Ok');
})()
141
void

これらのどれも括弧なしでは機能しません。

どうして?

仕様によると:

  1. ArrowFunctionAssignmentExpressionの下にリストされている
  2. CallExpression のLHSは、MemberExpressionSuperCallまたはCallExpression

そのため、ArrowFunctionCallExpressionのLHS上に存在できません。


これが=>の解釈方法で効果的に意味するのは、割り当て演算子=+=などと同じ種類のレベルで動作することです。

意味

  • x => {foo}()does n't(x => {foo})()になります
  • インタープリターはそれをx => ({foo}())として解釈しようとします
  • したがって、まだSyntaxError
  • そのため、インタプリタは(が間違っているに違いないと判断し、SyntaxErrorをスローします

Babelにはそれについてバグがありました here もあります。

17
Paul S.

このような問題が発生するのは、コンソール自体が現在ターゲットにしているコンテキストのグローバルスコープをエミュレートしようとするためです。また、コンソールで作成したステートメントおよび式から戻り値をキャプチャして、結果として表示されるようにします。例えば:

> 3 + 2
< 5

ここでは、あたかも式であるかのように実行されますが、あたかも文であるかのように記述しました。通常のスクリプトでは、値は破棄されますが、ここでは、コードを内部的にマングルする必要があります(関数コンテキストとreturnステートメントでステートメント全体をラップするなど)。 。

これは、スクリプト内のいくつかのベアES6コードが正常に機能するが、Chrome Dev Toolsコンソールでは機能しない理由の1つでもあります。

NodeおよびChromeコンソールでこれを実行してみてください:

{ let a = 3 }

Nodeまたは<script>タグでは正常に機能しますが、コンソールではUncaught SyntaxError: Unexpected identifierを提供します。また、VMxxx:1の形式でソースへのリンクが提供されます。このリンクをクリックすると、評価されたソースを検査できます。

({ let a = 3 })

なぜこれをしたのですか?

答えは、結果を呼び出し元に返してコンソールに表示できるように、コードを式に変換する必要があるということです。これを行うには、ステートメントを括弧で囲み、式にしますが、上記のブロックが構文的に不正になります(式にブロック宣言を含めることはできません)。

コンソールは、コードを賢くすることでこれらのEdgeのケースを修正しようとしますが、それはこの答えの範囲を超えていると思います。バグを報告して、それが修正を検討しているものかどうかを確認できます。

これは非常によく似た例です:

https://stackoverflow.com/a/28431346/46588

コードを機能させる最も安全な方法は、式として実行できることを確認し、SyntaxErrorソースリンクを調べて実際の実行コードが何であるかを確認し、そこからソリューションをリバースエンジニアリングすることです。通常、戦略的に配置された括弧のペアを意味します。

要するに:コンソールはグローバル実行コンテキストを可能な限り正確にエミュレートしようとしますが、v8エンジンとJavaScriptセマンティクスとの相互作用の制限により、これは解決が困難または不可能な場合があります。

2
Klemen Slavič