10. デストラクチャリング

10. デストラクチャリング#

  • 10.1. 10.1.1.概要
    • 10.1.1. オブジェクトの破棄
    • 10.1.2. 配列の破壊
    • 10.1.3. 破壊はどこで使用できますか?
  • 10.2. 背景:データの構築とデータの抽出
  • 10.3. 破壊のためのパターン
    • 10.3.1. あなたが必要なものを選ぶ
  • 10.4. パターンはどのように値の内臓にアクセスしますか?
    • 10.4.1. オブジェクトパターンは値をオブジェクト
    • 10.4.2に強制します。 配列パターンはiterablesで動作します
  • 10.5. デフォルト値
    • 10.5.1. undefinedはデフォルト値
    • 10.5.2をトリガします。 デフォルト値は、オンデマンド
    • 10.5.3で計算されます。 デフォルト値は、パターン
    • 10.5.4の他の変数を参照できます。 パターンのデフォルト値
    • 10.5.5. より複雑なデフォルト値
  • 10.6. より多くのオブジェクト破壊機能
    • 10.6.1. プロパティ値の省略形
    • 10.6.2. 計算されたプロパティキー
  • 10.7. より多くの配列破壊機能
    • 10.7.1. Elision
    • 10.7.2. Rest演算子(...)
  • 10.8. 変数
  • 10.9以上に割り当てることができます。 破壊の落とし穴
    • 10.9.1. 中括弧で文を開始しないでください
  • 10.10. 破壊の例
    • 10.10.1. 破壊は、配列
    • 10.10.2を返しました。 破棄が返されたオブジェクト
    • 10.10.3. 10.10.4.配列破壊反復可能な値
    • 10.10.4. 複数の戻り値
  • 10.11. 破壊アルゴリズム
    • 10.11.1. アルゴリズム
    • 10.11.2. アルゴリズムの適用

10.1 概要#

デストラクチャリングは、オブジェクトや配列に格納されている(ネストされている可能性がある)データから複数の値を抽出する便利な方法です。 これは、データを受信する場所(割り当ての左側など)で使用できます。 値を抽出する方法は、パターンを介して指定されます(例を参照)。

10.1.1オブジェクトの破壊#

オブジェクトの破壊:

const obj = { first: 'Jane', last: 'Doe' };const {first: f, last: l} = obj; // f = 'Jane'; l = 'Doe'// {prop} is short for {prop: prop}const {first, last} = obj; // first = 'Jane'; last = 'Doe'

破棄は戻り値の処理に役立ちます:

const obj = { foo: 123 };const {writable, configurable} = Object.getOwnPropertyDescriptor(obj, 'foo');console.log(writable, configurable); // true true

10.1.2 配列の破棄#

配列の破棄(すべての反復可能な値に対して機能します):

const iterable = ;const  = iterable; // x = 'a'; y = 'b'

破棄は戻り値の処理に役立ちます:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec('2999-12-31');

10.1.3 破壊はどこで使用できますか? #

破壊は次の場所で使用できます(私は示すために配列パターンを示しています;オブジェクトパターンも同様に動作します):

// Variable declarations:const  = ;let  = ;var  = ;// Assignments: = ;// Parameter definitions:function f() { ··· }f();

また、for-ofループで破壊することもできます:

const arr = ;for (const  of arr.entries()) { console.log(index, element);}// Output:// 0 a// 1 b

10.2 背景:データの構築とデータの抽出#

破壊とは何かを完全に理解するために、まずそのより広い文脈を調べてみましょう。

JavaScriptは、一度に一つのプロパティをデータを構築するための操作を持っています:

const obj = {};obj.first = 'Jane';obj.last = 'Doe';

同じ構文を使用してデータを抽出できます。 再び、一度に一つのプロパティ:

const f = obj.first;const l = obj.last;

さらに、オブジェクトリテラルを介して複数のプロパティを同時に構築する構文があります:

const obj = { first: 'Jane', last: 'Doe' };

ES6以前は、データを抽出するための対応するメカニズムはありませんでした。 これは、オブジェクトパターンを介してオブジェクトから複数のプロパティを抽出することができます。 たとえば、割り当ての左側には、次のように表示されます:

const { first: f, last: l } = obj;

パターンを介して配列を破壊することもできます:

const  = ; // x = 'a'; y = 'b'

10.破壊のための3つのパターン#

破壊には以下の二つの当事者が関与しています:

  • Destructuring source:destructuredされるデータ。 たとえば、分割代入の右側です。
  • Destructuring target:destructuringに使用されるパターン。 たとえば、分割代入の左側です。

破壊対象は三つのパターンのいずれかです:

  • 割り当て対象。 例えば: x
    • 代入対象は、通常は変数です。 しかし、destructuring assignmentでは、後で説明するように、より多くのオプションがあります。
  • オブジェクトパターン。 例えば: { first: "pattern", last: "pattern" }
    • オブジェクトパターンの部分はプロパティであり、プロパティ値は再びパターンです(再帰的に)。
  • 配列パターン。 例えば:
    • 配列パターンの部分は要素であり、要素は再びパターンです(再帰的に)。

つまり、パターンを任意に深く入れ子にすることができます:

const obj = { a: , b: true };const { a:  } = obj; // f = 123

10.3.1必要なものを選ぶ#

オブジェクトを破壊する場合は、興味のあるプロパティだけを言及します:

const { x: x } = { x: 7, y: 3 }; // x = 7

配列を破壊する場合は、接頭辞のみを抽出することを選択できます:

const  = ; // x='a'; y='b';

10.4 パターンはどのように値の内臓にアクセスしますか? #

割り当てpattern = someValueでは、patternsomeValue内のものにどのようにアクセスしますか?

10.4.1オブジェクトパターンは値をオブジェクトに強制します#

オブジェクトパターンは、プロパティにアクセスする前にソースをオブジェクトに強制 つまり、プリミティブ値で動作することを意味します:

const {length : len} = 'abc'; // len = 3const {toString: s} = 123; // s = Number.prototype.toString
10.4.1.1 値#

オブジェクトの破壊に失敗した場合、オブジェクトへの強制はObject()ではなく、内部操作ToObject()を介して実行されます。 2つの操作は、undefinednullを別々に処理します。

Object()プリミティブ値をラッパーオブジェクトに変換し、オブジェクトをそのまま残します:

> typeof Object('abc')'object'> var obj = {};> Object(obj) === objtrue

It also converts undefined and null to empty objects:

> Object(undefined){}> Object(null){}

In contrast, ToObject() throws a TypeError if it encounters undefined or null. Therefore, the following destructurings fail, even before destructuring accesses any properties:

const { prop: x } = undefined; // TypeErrorconst { prop: y } = null; // TypeError

その結果、空のオブジェクトパターン{}を使用して、値がオブジェクトに強制可能かどうかを確認できます。 我々が見てきたように、undefinednullだけがそうではありません:

({} = ); // OK, Arrays are coercible to objects({} = 'abc'); // OK, strings are coercible to objects({} = undefined); // TypeError({} = null); // TypeError

JavaScriptでは文の先頭が中括弧であってはならないため、式の周りの括弧が必要です(詳細は後述します)。

10.4.2配列パターンはiterablesで動作します#

配列破壊は、イテレータを使用してソースの要素を取得します。 したがって、反復可能な任意の値を配列破壊することができます。 反復可能な値の例を見てみましょう。

文字列は反復可能です:

const  = 'abc'; // x='a'; y=

文字列に対するイテレータは、コード単位(”JavaScript文字”、16ビット)ではなく、コードポイント(”Unicode文字”、21ビット)を返すことを忘れないでください。 (Unicodeの詳細については、”第24章”の章を参照してください。 UnicodeとJavaScript”で”Javascriptを話す”。)例えば:

const  = 'a\uD83D\uDCA9c'; // x='a'; y='\uD83D\uDCA9'; z='c'

インデックスを介してセットの要素にアクセスすることはできませんが、イテレータを介してアクセスできます。 したがって、配列の破壊は集合に対して機能します:

const  = new Set(); // x='a'; y='b';

Setイテレータは、要素が挿入された順序で常に返されるため、前の破棄の結果は常に同じになります。

10.4.2.1値の配列破壊に失敗しました#

キーがSymbol.iteratorでオブジェクトを返すメソッドがある場合、値は反復可能です。 Array-destructuringは、破棄される値が反復可能でない場合、TypeErrorをスローします:

let x; = ; // OK, Arrays are iterable = 'abc'; // OK, strings are iterable = { * () { yield 1 } }; // OK, iterable = {}; // TypeError, empty objects are not iterable = undefined; // TypeError, not iterable = null; // TypeError, not iterable

つまり、空の配列パターンを使用して、値が反復可能かどうかを確認できます。TypeErrorは、iterableの要素にアクセスする前であってもスローされます。は、値がiterableかどうかを:

 = {}; // TypeError, empty objects are not iterable = undefined; // TypeError, not iterable = null; // TypeError, not iterable

10.5 デフォルト値#

デフォルト値はパターンのオプション機能です。 ソースに何も見つからない場合は、フォールバックを提供します。 部分(オブジェクトプロパティまたは配列要素)がソース内に一致しない場合、それは次の要素と照合されます:

  • デフォルト値(指定されている場合; それは任意です)
  • undefined (それ以外の場合)

例を見てみましょう。 次の分割では、インデックス0の要素は右側に一致しません。 したがって、破壊はxと3を一致させることによって継続され、xは3に設定されます。

const  = ; // x = 3; y = undefined

オブジェクトパターンで既定値を使用することもできます:

const {foo: x=3, bar: y} = {}; // x = 3; y = undefined

10.5.1 undefined トリガのデフォルト値#

デフォルト値は、パーツに一致があり、その一致がundefinedの場合にも使用されます:

const  = ; // x = 1const {prop: y=2} = {prop: undefined}; // y = 2

この動作の理論的根拠については、次の章の”パラメータのデフォルト値”のセクションで説明します。

10.5.2デフォルト値はオンデマンドで計算されます#

デフォルト値自体は必要なときにのみ計算されます。 言い換えれば、この破壊:

const {prop: y=someFunc()} = someValue;

と等価である。:

let y;if (someValue.prop === undefined) { y = someFunc();} else { y = someValue.prop;}

あなたが使用する場合、あなたはそれを観察することができますconsole.log():

> function log(x) { console.log(x); return 'YES' }> const = ;> a'YES'> const = ;> b123

In the second destructuring, the default value is not triggered and log() is not called.

10.5.3 Default values can refer to other variables in the pattern #

A default value can refer to any variable, including other variables in the same pattern:

const  = ; // x=3; y=3const  = ; // x=7; y=7const  = ; // x=7; y=2

しかし、注文事項: 変数xyは左から右に宣言され、宣言の前にアクセスされた場合はReferenceErrorを生成します:

const  = ; // ReferenceError

10.5.4 パターンのデフォルト値#

これまでのところ、変数のデフォルト値のみを見てきましたが、それらをパターンに関連付けることもできます:

const  = ;

これはどういう意味ですか? デフォルト値のルールを思い出してください:パーツにソースに一致するものがない場合、デストラクチャリングはデフォルト値で続行されます。

インデックス0の要素には一致しないため、破壊が続行されます:

const { prop: x } = {}; // x = undefined

パターン{ prop: x }を変数に置き換えると、このように動作する理由をより簡単に確認できますpattern:

const  = ;

10.5.5 より複雑なデフォルト値#

パターンのデフォルト値をさらに調べてみましょう。 次の例では、デフォルト値{ prop: 123 }を使用してxに値を割り当てます:

const  = ;

インデックス0の配列要素は右側に一致しないため、次のように分割が続行され、xが123に設定されます。

const { prop: x } = { prop: 123 }; // x = 123

ただし、右側にインデックス0の要素がある場合、デフォルト値はトリガーされないため、xにはこの方法で値が割り当てられません。

const  = ;

この場合、破壊は次のように続きます:

const { prop: x } = {}; // x = undefined

したがって、オブジェクトまたはプロパティのいずれかが欠落している場合にxを123にする場合は、x自体にデフォルト値を指定する必要があります:

const  = ;

ここでは、右辺がであるかであるかにかかわらず、破壊は次のように続きます。

const { prop: x=123 } = {}; // x = 123

10.6 その他のオブジェクト分割機能#

10.6.1プロパティ値の省略形#

プロパティ値の省略形は、オブジェクトリテラルの機能です: プロパティ値がプロパティキーと同じ名前の変数である場合は、キーを省略できます。 これは、あまりにも、破壊のために動作します:

const { x, y } = { x: 11, y: 8 }; // x = 11; y = 8// Same as:const { x: x, y: y } = { x: 11, y: 8 };

また、プロパティ値の省略形を既定値と組み合わせることもできます:

const { x, y = 1 } = {}; // x = undefined; y = 1

10.6.2 計算されたプロパティキー#

計算されたプロパティキーは、破壊にも機能する別のオブジェクトリテラル機能です。 プロパティのキーは、角括弧に入れた場合、式を介して指定できます:

const FOO = 'foo';const { : f } = { foo: 123 }; // f = 123

計算されたプロパティキーを使用すると、キーがシンボルであるプロパティを:

// Create and destructure a property whose key is a symbolconst KEY = Symbol();const obj = { : 'abc' };const { : x } = obj; // x = 'abc'// Extract Array.prototypeconst { : func } = ;console.log(typeof func); // function

10.7 その他の配列破壊機能#

10.7.1Elision#

Elisionでは、配列”穴”の構文を使用して、破壊中に要素をスキップできます:

const  = ; // x = 'c'; y = 'd'

10.7.2 Rest演算子(...) #

rest演算子を使用すると、iterableの残りの要素を配列に抽出できます。 この演算子が配列パターン内で使用されている場合は、最後に来る必要があります:

const  = ; // x='a'; y=

演算子が要素を見つけることができない場合は、空の配列に対してオペランドと一致します。 つまり、undefinedまたはnullは生成されません。 例えば:

const  = ; // x='a'; y=undefined; z=

rest演算子のオペランドは変数である必要はなく、パターンも使用できます:

const ] = ; // x = 'a'; y = 'b'; z = 'c'

rest演算子は、次の破壊をトリガーします:

 = 

10.8変数以外にも割り当てることができます#

分割を介して割り当てる場合、各割り当てターゲットは通常の割り当ての左側で許可されているすべてのものにすることができます。

たとえば、プロパティへの参照(obj.prop):

const obj = {};({ foo: obj.prop } = { foo: 123 });console.log(obj); // {prop:123}

または配列要素への参照(arr):

const arr = ;({ bar: arr } = { bar: true });console.log(arr); // 

rest演算子(...)を使用して、オブジェクトプロパティと配列要素に割り当てることもできます:

const obj = {}; = ; // first = 'a'; obj.prop = 

変数を宣言したり、分割を介してパラメータを定義したりする場合は、単純な識別子を使用する必要があります。

10.9デストラクチャリングの落とし穴#

デストラクチャを使用するときに注意すべきことが二つあります:

  • 中括弧で文を開始することはできません。
  • デストラクチャ中に、変数を宣言するか、変数に割り当てることができますが、両方はできません。

次の二つのセクションには詳細が含まれています。

10.9.1中括弧で文を開始しないでください#

コードブロックは中括弧で始まるため、文は中括弧で始まってはいけません。 これは、代入でオブジェクトの破壊を使用する場合には残念です:

{ a, b } = someObject; // SyntaxError

回避策は、完全な式を括弧内に入れることです:

({ a, b } = someObject); // OK

次の構文は機能しません:

({ a, b }) = someObject; // SyntaxError

letvarconstでは、中括弧が問題を引き起こすことはありません:

const { a, b } = someObject; // OK

10.10個の破壊の例#

いくつかの小さな例から始めましょう。

for-ofループは破壊をサポートしています:

const map = new Map().set(false, 'no').set(true, 'yes');for (const  of map) { console.log(key + ' is ' + value);}

分割を使用して値を交換することができます。 これは、エンジンが最適化できるため、配列が作成されないようにするものです。

 = ;

分割を使用して配列を分割することができます:

const  = ; // first = 'a'; rest = 

10.10.1 返された配列の破棄#

組み込みのJavaScript操作の中には、配列を返すものがあります。 破壊はそれらを処理するのに役立ちます:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec('2999-12-31');

グループのみに関心がある場合(完全な一致ではなく、all)、elisionを使用してインデックスの配列要素をスキップすることができます0:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec('2999-12-31');

exec() 正規表現が一致しない場合は、nullを返します。 残念ながら、デフォルト値でnullを処理することはできないため、この場合はOr演算子(||)を使用する必要があります:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec(someStr) || ;

Array.prototype.split() 配列を返します。 したがって、配列ではなく要素に興味がある場合は、破壊が便利です:

const cells = 'Jane\tDoe\tCTO'const  = cells.split('\t');console.log(firstName, lastName, title);

10.10.2 destructuring returned objects#

Destructuringは、関数またはメソッドによって返されるオブジェクトからデータを抽出するのにも役立ちます。 たとえば、イテレータメソッドnext()は、donevalueの2つのプロパティを持つオブジェクトを返します。 次のコードは、Iteratoriterを介してArrayarrのすべての要素をログに記録します。 A行目では破壊が使用されます。

const arr = ;const iter = arr();while (true) { const {done,value} = iter.next(); // (A) if (done) break; console.log(value);}

10.10.3 Array-destructuring iterable values#

Array-destructuringは任意の反復可能な値で動作します。 それは時折便利です:

const  = new Set().add('a').add('b'); // x = 'a'; y = 'b'const  = 'foo'; // a = 'f'; b = 'o'

10.10.4 複数の戻り値#

複数の戻り値の有用性を確認するには、関数ptrueを返す配列aの最初の要素を検索する関数findElement(a, p)を実装しましょう。 問題は、findElement()は何を返すべきかです。 時には、要素自体に、時にはそのインデックスに、時には両方に興味があることもあります。 次の実装では、両方を返します。

function findElement(array, predicate) { for (const  of array.entries()) { // (A) if (predicate(element, index, array)) { // We found an element: return { element, index }; // Same as (property value shorthands): // { element: element, index: index } } } // We couldn't find anything; return failure values: return { element: undefined, index: -1 };}

この関数は、配列メソッドentries()を介してarrayのすべての要素を反復処理し、ペア(行A)に対する反復可能な値を返します。 ペアの部分は、破壊を介してアクセスされます。

findElement():

const arr = ;const {element, index} = findElement(arr, x => x % 2 === 0); // element = 8, index = 1

ECMAScript6のいくつかの機能により、より簡潔なコードを記述することができました。コールバックは矢印関数です。戻り値はプロパティ値の省略形を持つオブジェクトパターンを介して破棄されます。

indexelementもプロパティキーを参照しているため、それらを言及する順序は問題ではありません。 我々はそれらを交換することができ、何も変更されません:

const {index, element} = findElement(···);

我々は正常にインデックスと要素の両方を必要とする場合を処理しました。 私たちがそのうちの1つだけに興味がある場合はどうなりますか? ECMAScript6のおかげで、私たちの実装もそれを処理できることがわかりました。 また、単一の戻り値を持つ関数と比較した構文上のオーバーヘッドは最小限です。

const a = ;const {element} = findElement(a, x => x % 2 === 0); // element = 8const {index} = findElement(a, x => x % 2 === 0); // index = 1

毎回、必要な1つのプロパティの値のみを抽出します。

10.11destructuring algorithm#

このセクションでは、再帰的なパターンマッチングアルゴリズムとして、別の角度からdestructuringを見ています。

最後に、アルゴリズムを使用して、次の2つの関数宣言の違いを説明します。

function move({x=0, y=0} = {}) { ··· }function move({x, y} = { x: 0, y: 0 }) { ··· }

10.11.1 アルゴリズム#

分割代入は次のようになります:

"pattern" = "value"

patternを使用してvalueからデータを抽出します。 ここでは、関数型プログラミングでパターンマッチング(略してマッチング)として知られているそのためのアルゴリズムについて説明します。 このアルゴリズムは、patternvalueに一致し、そうしている間に変数に代入する分割代入のための演算子(“match against”)を指定します:

"pattern"  "value"

このアルゴリズムは、演算子の両方のオペランドを分解する再帰規則によって指定されます。 宣言的表記法には慣れるまでに時間がかかるかもしれませんが、アルゴリズムの仕様をより簡潔にします。 各ルールには2つの部分があります:

  • 先頭(最初の行)には、ルールをトリガーする条件が記述されています。
  • 本文(残りの行)は、ルールがトリガーされた場合の処理を記述します。

例を見てみましょう:

  • (2c) {key: "pattern", "properties"} ← obj
     "pattern"  obj.key {"properties"}  obj
  • (2e){} ← obj(プロパティが残っていません)
     // Nothing to do

ルール(2c)では、headは、少なくとも一つのプロパティとゼロ以上の残りのプロパティを持つオブジェクトパターンがある場合、このルールが実行されるこ そのパターンは値objと照合されます。 このルールの効果は、プロパティ値パターンがobj.keyと照合され、残りのプロパティがobjと照合されて実行が続行されることです。

ルール(2e)では、headは、空のオブジェクトパターン{}が値objと一致した場合、このルールが実行されることを意味します。 その後、何もすることはありません。

アルゴリズムが呼び出されるたびに、ルールは上から下にチェックされ、適用可能な最初のルールのみが実行されます。

私は分割代入のアルゴリズムのみを示しています。 変数宣言の破棄とパラメータ定義の破棄も同様に機能します。

私は高度な機能をカバーしていません(計算されたプロパティキー、プロパティ値の省略形; オブジェクトのプロパティと配列要素を代入対象として)。 基本だけ。

10.11.1.1パターン#

パターンは次のいずれかです:

  • 変数: x
  • オブジェクトパターン: {"properties"}
  • 配列パターン:

以下の各セクションでは、これら3つのケースのいずれかについて説明します。

以下の三つのセクションでは、これら三つのケースの処理方法を指定しています。 各セクションには、1つ以上の番号付きルールが含まれています。

10.11.1.2変数#
  • (1) x ← value (undefinedを含むお絵かき掲示板null)
     x = value
10.11.1.3 オブジェクトパターン#
  • (2a) {"properties"} ← undefined
     throw new TypeError();
  • (2b) {"properties"} ← null
     throw new TypeError();
  • (2c) {key: "pattern", "properties"} ← obj
     "pattern"  obj.key {"properties"}  obj
  • (2次元) {key: "pattern" = default_value, "properties"} ← obj
     const tmp = obj.key; if (tmp !== undefined) { "pattern"  tmp } else { "pattern"  default_value } {"properties"}  obj
  • (2e){} ← obj(プロパティが残っていません)
     // Nothing to do
10.11.1.4 配列パターン#

配列パターンとiterable。 配列分割のアルゴリズムは、配列パターンとiterableから始まります:

  • (3a) ← non_iterable
    assert(!isIterable(non_iterable))
     throw new TypeError();
  • (3b) ← iterable
    assert(isIterable(iterable))
     const iterator = iterable(); "elements"  iterator

ヘルパー関数:

function isIterable(value) { return (value !== null && typeof value === 'object' && typeof value === 'function');}

配列要素とイテレータ。 このアルゴリズムは、パターンの要素(矢印の左側)と、iterableから取得したイテレータ(矢印の右側)に続きます。

  • (3c) "pattern", "elements" ← iterator
     "pattern"  getNext(iterator) // undefined after last item "elements"  iterator
  • (3d) "pattern" = default_value, "elements" ← iterator
     const tmp = getNext(iterator); // undefined after last item if (tmp !== undefined) { "pattern"  tmp } else { "pattern"  default_value } "elements"  iterator
  • (3e), "elements" ← iterator(穴、省略)
     getNext(iterator); // skip "elements"  iterator
  • (3f)..."pattern" ← iterator(常に最後の部分!)
     const tmp = ; for (const elem of iterator) { tmp.push(elem); } "pattern"  tmp
  • (3g)← iterator(要素が残っていません)
     // Nothing to do

ヘルパー関数:

function getNext(iterator) { const {done,value} = iterator.next(); return (done ? undefined : value);}

10.11.2 アルゴリズム#

をECMAScript6で適用すると、呼び出し元がオブジェクトリテラルを使用し、呼び出し先が破壊を使用する場合、名前付きパラメータをシミュ このシミュレーションについては、パラメータ処理の章で詳しく説明します。 次のコードは例を示しています。functionmove1()には、xxという2つの名前付きパラメーターがありますy:

function move1({x=0, y=0} = {}) { // (A) return ;}move1({x: 3, y: 8}); // move1({x: 3}); // move1({}); // move1(); // 

行Aには3つのデフォルト値があります:

  • 最初の2つのデフォルト値を使用すると、xyを省略できます。
  • 3番目のデフォルト値を使用すると、(最後の行のように)パラメータなしでmove1()を呼び出すことができます。

しかし、なぜ前のコードスニペットのようにパラメータを定義するのですか? なぜ次のように–また、完全に合法的なES6コードですか?

function move2({x, y} = { x: 0, y: 0 }) { return ;}

なぜmove1()が正しいのかを確認するために、2つの例で両方の関数を使用しましょう。 それを行う前に、パラメータの渡しがマッチングによってどのように説明できるかを見てみましょう。

10.11.2.1背景:マッチング#

を介してパラメータを渡す関数呼び出しの場合、仮パラメータ(関数定義内)は、実際のパラメータ(関数呼び出し内)と照合されます。 例として、次の関数定義と次の関数呼び出しを考えてみましょう。

function func(a=0, b=0) { ··· }func(1, 2);

パラメータabは、次の破壊と同様に設定されます。

  
10.11.2.2 を使用してmove2() #

move2()の破壊がどのように機能するかを調べてみましょう。

例1. move2():

  

左側の単一の配列要素は右側に一致しないため、{x,y}は右側のデータではなくデフォルト値と一致します(ルール3b、3d):

{x, y}  { x: 0, y: 0 }

左側にはプロパティ値の省略形が含まれています。:

{x: x, y: y}  { x: 0, y: 0 }

この分割により、次の二つの割り当てが行われます(ルール2c, 1):

x = 0;y = 0;

例2. 次の破壊につながる関数呼び出しmove2({z:3})を調べてみましょう:

  

右側のインデックス0に配列要素があります。 したがって、デフォルト値は無視され、次のステップは(rule3d)です。:

{x, y}  { z: 3 }

これにより、xyの両方がundefinedに設定されますが、これは私たちが望むものではありません。

10.11.2.3move1() #

move1()を試してみましょう。

1: move1()

  

右側のインデックス0に配列要素がなく、デフォルト値(ルール3d)を使用します):

{x=0, y=0}  {}

左側にはプロパティ値の省略形が含まれています。:

{x: x=0, y: y=0}  {}

プロパティxもプロパティyも右側に一致しません。 したがって、デフォルト値が使用され、次に次の破壊が実行されます(ルール2d):

x  0y  0

これにより、次の割り当て(ルール)が行われます1):

x = 0y = 0

例2: move1({z:3})

  

配列パターンの最初の要素には右側に一致があり、その一致は破壊を続行するために使用されます(ルール3d):

{x=0, y=0}  {z:3}

例1のように、右側にプロパティxyがなく、既定値が使用されます:

x = 0y = 0
10.11.2.4 結論#

この例では、デフォルト値がパターン部分(オブジェクトプロパティまたは配列要素)の機能であることを示しています。 部品に一致がない場合、またはundefinedと一致する場合は、デフォルト値が使用されます。 つまり、パターンは代わりにデフォルト値と照合されます。