46

「スプレッド構文」と「スプレッド演算子...」の両方と呼ばれるのを聞いたことがありますが、後者の方がはるかに一般的です。関連するMDN ドキュメントの URL は、最初はスプレッド演算子と呼ばれていたが、後にスプレッド構文に変更されたことを示唆しており、 MDN の演算子のリストには言及されていません。

Google は、 Microsoft のドキュメントes6-features.orgなどのサイトで、オペレーターという用語がより一般的で受け入れられていることを示唆しているようです。

ECMAScript のコンテキストで最も正しい用語はどれですか? またその理由は? 配列破壊代入はどうですか?

4

2 に答える 2

84

オペレーターではありません。

言葉のあらゆる意味で、それは一つではありません。それが導入されて以来、一般的な意見にもかかわらず、それは大きな誤解でした - それは一つではなく、いくつかの客観的なポイントがあります:

  • 演算子の定義に適合しません
  • オペレーターとしては使えない
  • 言語仕様は、それが演算子ではないことを暗示しています

分散構文にはさまざまな「フレーバー」があり、さまざまなコンテキストで使用され、同じ句読点を使用しているにもかかわらず、一般的にさまざまな名前で参照されることに注意してください。スプレッド構文は、基本的に...句読点のアプリケーションの包括的な用語であり、すべての使用法と名前を詳述しているFelix Klingの素晴らしい回答を参照してください。これらの個人の使用に関する詳細な説明は、補足回答に記載されています。

オペレーターとは?

意味的には、ECMAScript のコンテキストでは、演算子は、引数を取り、単一の値に評価される単なる組み込み関数です。プレフィックス、インフィックス、またはポストフィックスの表記法で記述され、通常は+またはなどの記号名が付いてい/ます。ウィキペディアから:

簡単に言えば、演算子を含む式は何らかの方法で評価され、結果の値は単なる値 (右辺値) になるか、代入を許可するオブジェクト (左辺値) になります。

たとえば、+演算子は右辺の式である 2 などの値になり、.演算子の結果は、左辺の式である などの代入を許可するオブジェクトになりますfoo.bar

表面的には、...句読点1は前置単項演算子のように見えます。

const baz = [foo, ...bar];

しかし、その引数の問題は、それ...barが特異値に評価されないことです。iterablebarの要素を 1 つずつ展開します。同じことがスプレッド引数にも当てはまります。

foo(...bar);

ここで、 iterable から個別fooの引数を受け取ります。これらは、1 つの値だけではなく、に渡される個別の値です。演算子の定義に適合しないため、演算子ではありません。barfoo

なんでオペレーターじゃないの?

もう 1 つの注意点は、演算子はスタンドアロンであり、単一の値を返すことを意図しているということです。例えば:

const bar = [...foo];

すでに述べたように、これはうまく機能します。これを行おうとすると問題が発生します。

const bar = ...foo;

スプレッド構文が演算子である場合、演算子は式を単一の値に評価するため、後者は正常に機能しますが、スプレッドはそうではないため、失敗します。分散構文と分散引数は、配列と関数呼び出しのコンテキストでのみ機能します。これらの構造は、分散配列要素または引数によって提供される複数の値を受け取るためです。複数の値への評価は、オペレーターが実行できる範囲外です。

基準は何と言っていますか?

演算子の完全なリストは、 ECMAScript 2015 言語仕様の条項 §12.5 から §12.15 に記載されて......ます。演算子ではないことも推測できます。この回答で言及されている、関数呼び出し (スプレッド引数) または配列リテラル(スプレッド構文) のスプレッド構文が生成される 2 つの主なケースを以下に説明します。

配列リテラル:
  【エリシオンオプト】
  [要素リスト]
  [ ElementList 、 Elisionopt ]

要素リスト:
  Elision opt AssignmentExpression
  Elision opt SpreadElement
  ElementList , Elision opt AssignmentExpression
  ElementList , Elision opt SpreadElement

エリシオン:
  、
  エリシオン、

SpreadElement :
  ...代入式
  

関数呼び出しの場合:

CallExpression :
  メンバー式の引数

引数:
  ( )
  (引数リスト)

引数リスト:
  代入式
  ...代入式
  ArgumentList 、代入式
  ArgumentList , ...代入式
  

これらの作品では、スプレッド「オペレーター」は存在しないという結論が得られます。前述のように、演算子は と のようにスタンドアロンである必要があり、const bar = ...foo単一の値に評価されます。言語の構文はこれを防ぎます。つまり、拡散構文はスタンドアロンであることを意図したものではありませんでした。これは、配列初期化子と関数呼び出しの拡張であり、文法の拡張です。

「構文」を広める理由

ウィキペディアで定義されている構文:

コンピューター サイエンスでは、コンピューター言語の構文は、その言語で正しく構造化されたドキュメントまたはフラグメントと見なされる記号の組み合わせを定義する一連の規則です。

構文は基本的に言語の「形式」であり、コードがどのように見えるべきか、コードがどのように書かれるべきかに関して何が合法であるかを管理する規則です。この場合、ECMAScript の文法では、...句読点が拡張機能として関数呼び出しと配列リテラルにのみ現れるように明確に定義されています。これは、...foo一緒に正当であると見なされる記号 ( ) の組み合わせを定義する規則です。したがって、構文は次のようになります。アロー関数 ( =>) は演算子ではなく、構文2です。

オペレーターを呼ぶ...のは誤解です。演算子は、引数 (オペランド) を受け取る組み込み関数であり、前置、中置、または後置表記の形式であり、正確に 1 つの値に評価されます...は、最初の 2 つの条件を満たしていますが、最後の条件を満たしていません。...代わりに、言語の文法で具体的かつ明示的に定義されているため、構文です。したがって、「拡散演算子」は、客観的には「拡散構文」としてより正確に参照されます。


1 「パンクチュエーター」という用語は、ECMAScript 2015以降の仕様のパンクチュエーターを指します。これらの記号には、構文コンポーネントと演算子が含まれており、言語の句読点です。...はパンクチュエータそのものですが、「拡散構文」という用語は、パンクチュエータの適用全体を指します。

2 =>自体はpunctuatorです...が、私が具体的に言及しているのはアロー関数構文、つまり=>punctuator ( (…) => { … })の適用であり、拡散構文が punctuatorの適用を指すのと同じ...です。

于 2017-07-05T19:49:51.013 に答える