10. デストラクチャリング
目次
本書をサポートしていただけますか? 購入 (PDF, EPUB, MOBI) または 寄付 をお願いします。
(広告です。ブロックしないでください。)

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



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 = ['a', 'b'];
const [x, y] = iterable;
    // x = 'a'; y = 'b'

デストラクチャリングは戻り値の処理に役立ちます

const [all, year, month, day] =
    /^(\d\d\d\d)-(\d\d)-(\d\d)$/
    .exec('2999-12-31');

10.1.3 デストラクチャリングはどこで使用できますか?

デストラクチャリングは次の場所で使用できます(配列パターンを示していますが、オブジェクトパターンも同様に機能します)。

// Variable declarations:
const [x] = ['a'];
let [x] = ['a'];
var [x] = ['a'];

// Assignments:
[x] = ['a'];

// Parameter definitions:
function f([x]) { ··· }
f(['a']);

for-ofループでもデストラクチャリングできます。

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

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

デストラクチャリングが何かを完全に理解するには、まずその広いコンテキストを調べましょう。

JavaScriptには、一度に1つのプロパティでデータを構築する操作があります。

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

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

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

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

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

ES6以前は、データ抽出に対応するメカニズムがありませんでした。それがデストラクチャリングです。オブジェクトから複数のプロパティをオブジェクトパターンを使用して抽出できます。たとえば、代入の左辺で。

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

パターンを使用して配列をデストラクチャリングすることもできます。

const [x, y] = ['a', 'b']; // x = 'a'; y = 'b'

10.3 デストラクチャリングのパターン

デストラクチャリングには次の2つの当事者が関係しています。

デストラクチャリングターゲットは、次の3つのパターンのいずれかです。

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

const obj = { a: [{ foo: 123, bar: 'abc' }, {}], b: true };
const { a: [{foo: f}] } = obj; // f = 123

10.3.1 必要に応じて選択する

オブジェクトをデストラクチャリングする場合、関心のあるプロパティのみを指定します。

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

配列をデストラクチャリングする場合は、プレフィックスのみを抽出するように選択できます。

const [x,y] = ['a', 'b', 'c']; // x='a'; y='b';

10.4 パターンはどのように値の中身をアクセスしますか?

代入pattern = someValueでは、patternはどのようにsomeValueの中身をアクセスしますか?

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

オブジェクトパターンは、プロパティにアクセスする前に、デストラクチャリングソースをオブジェクトに強制変換します。つまり、プリミティブ値でも動作します。

const {length : len} = 'abc'; // len = 3
const {toString: s} = 123; // s = Number.prototype.toString
10.4.1.1 値のオブジェクトデストラクチャリングに失敗する

オブジェクトへの強制変換はObject()ではなく、内部操作ToObject()を介して実行されます。これら2つの操作は、undefinednullを異なる方法で処理します。

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

> typeof Object('abc')
'object'

> var obj = {};
> Object(obj) === obj
true

また、undefinednullを空のオブジェクトに変換します。

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

対照的に、ToObject()undefinedまたはnullに遭遇するとTypeErrorをスローします。したがって、次のデストラクチャリングは、デストラクチャリングがプロパティにアクセスする前でも失敗します。

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

結果として、空のオブジェクトパターン{}を使用して、値がオブジェクトに変換可能かどうかを確認できます。前述のように、undefinednullのみが変換できません。

({} = [true, false]); // OK, Arrays are coercible to objects
({} = 'abc'); // OK, strings are coercible to objects

({} = undefined); // TypeError
({} = null); // TypeError

式を囲む括弧は、JavaScriptではステートメントを中括弧で始めることができないため必要です(詳細は後で説明します)。

10.4.2 配列パターンはイテラブルと連携します

配列デストラクチャリングはイテレータを使用してソースの要素にアクセスします。したがって、イテラブルな値であれば、配列デストラクチャリングを使用できます。イテラブル値の例を見てみましょう。

文字列はイテラブルです。

const [x,...y] = 'abc'; // x='a'; y=['b', 'c']

文字列のイテレータは、コードユニット(「JavaScript文字」、16ビット)ではなく、コードポイント(「Unicode文字」、21ビット)を返すことに注意してください。(Unicodeの詳細については、「Speaking JavaScript」の「第24章 UnicodeとJavaScript」を参照してください)。たとえば、

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

インデックスを介してSetの要素にアクセスすることはできませんが、イテレータを介してアクセスできます。したがって、配列デストラクチャリングはSetでも機能します。

const [x,y] = new Set(['a', 'b']); // x='a'; y='b’;

Setイテレータは、常に挿入された順序で要素を返し、そのため、前のデストラクチャリングの結果は常に同じです。

10.4.2.1 値の配列デストラクチャリングに失敗する

値がイテラブルであるとは、キーがSymbol.iteratorであり、オブジェクトを返すメソッドを持つことを意味します。配列デストラクチャリングは、デストラクチャリングする値がイテラブルでない場合、TypeErrorをスローします。

let x;
[x] = [true, false]; // OK, Arrays are iterable
[x] = 'abc'; // OK, strings are iterable
[x] = { * [Symbol.iterator]() { yield 1 } }; // OK, iterable

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

TypeErrorは、イテラブルの要素にアクセスする前でもスローされます。つまり、空の配列パターン[]を使用して、値がイテラブルかどうかを確認できます。

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

10.5 デフォルト値

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

例を見てみましょう。次のデストラクチャリングでは、インデックス0の要素には右辺に一致するものがないため、デストラクチャリングはxと3の照合を続行し、xが3に設定されます。

const [x=3, y] = []; // x = 3; y = undefined

オブジェクトパターンでもデフォルト値を使用できます。

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

10.5.1 undefinedはデフォルト値をトリガーします

部分に一致するものがあり、その一致がundefinedの場合も、デフォルト値が使用されます。

const [x=1] = [undefined]; // x = 1
const {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=log('hello')] = [];
> a
'YES'

> const [b=log('hello')] = [123];
> b
123

2番目のデストラクチャリングでは、デフォルト値はトリガーされず、log()は呼び出されません。

10.5.3 デフォルト値はパターン内の他の変数を参照できます

デフォルト値は、同じパターン内の他の変数を含む、任意の変数を参照できます。

const [x=3, y=x] = [];     // x=3; y=3
const [x=3, y=x] = [7];    // x=7; y=7
const [x=3, y=x] = [7, 2]; // x=7; y=2

ただし、順序が重要です。変数xyは左から右に宣言され、宣言前にアクセスされるとReferenceErrorが発生します。

const [x=y, y=3] = []; // ReferenceError

10.5.4 パターンに対するデフォルト値

これまでは変数に対するデフォルト値しか見ていませんでしたが、パターンにも関連付けることができます。

const [{ prop: x } = {}] = [];

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

インデックス0の要素に一致するものがないため、デストラクチャリングは次のようになります。

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

パターン{ prop: x }を変数patternに置き換えると、動作がより分かりやすくなります。

const [pattern = {}] = [];

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

パターンに対するデフォルト値をさらに詳しく見てみましょう。次の例では、デフォルト値{ prop: 123 }を介してxに値を代入します。

const [{ prop: x } = { prop: 123 }] = [];

インデックス 0 の配列要素に右辺に相当するものが無い場合、デストラクチャリングは次のように継続し、x は 123 に設定されます。

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

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

const [{ prop: x } = { prop: 123 }] = [{}];

この場合、デストラクチャリングは次のように継続します。

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

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

const [{ prop: x=123 } = {}] = [{}];

ここでは、右辺が [{}][] かに関係なく、デストラクチャリングは次のように継続します。

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 { [FOO]: f } = { foo: 123 }; // f = 123

計算されたプロパティキーを使用すると、キーがシンボルであるプロパティをデストラクチャリングできます。

// Create and destructure a property whose key is a symbol
const KEY = Symbol();
const obj = { [KEY]: 'abc' };
const { [KEY]: x } = obj; // x = 'abc'

// Extract Array.prototype[Symbol.iterator]
const { [Symbol.iterator]: func } = [];
console.log(typeof func); // function

10.7 その他の配列デストラクチャリング機能

10.7.1 省略記法

省略記法を使用すると、配列の「穴」の構文を使用して、デストラクチャリング中に要素をスキップできます。

const [,, x, y] = ['a', 'b', 'c', 'd']; // x = 'c'; y = 'd'

10.7.2 レスト演算子 (...)

レスト演算子を使用すると、反復可能な要素の残りの要素を配列に抽出できます。この演算子を配列パターン内で使用する場合、最後に配置する必要があります。

const [x, ...y] = ['a', 'b', 'c']; // x='a'; y=['b', 'c']

演算子が要素を見つけられない場合、空の配列に対してオペランドを照合します。つまり、undefinednull を生成することはありません。例:

const [x, y, ...z] = ['a']; // x='a'; y=undefined; z=[]

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

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

レスト演算子は、次のデストラクチャリングをトリガーします。

[y, z] = ['b', 'c']

10.8 変数だけでなく、他のものにも代入できます

デストラクチャリングで代入する場合、各代入ターゲットは、通常の代入の左辺で許可されるすべてのものになります。

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

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

または、配列要素への参照 (arr[0])

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

レスト演算子 (...) を使用して、オブジェクトのプロパティと配列の要素にも代入できます。

const obj = {};
[first, ...obj.prop] = ['a', 'b', 'c'];
    // first = 'a'; obj.prop = ['b', 'c']

デストラクチャリングで変数を宣言したり、パラメーターを定義したりする場合は、単純な識別子を使用する必要があります。オブジェクトのプロパティや配列の要素を参照することはできません。

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

デストラクチャリングを使用する際には、2つの点に注意する必要があります。

次の2つのセクションでは、詳細を説明します。

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 [key, value] of map) {
  console.log(key + ' is ' + value);
}

デストラクチャリングを使用して値を交換できます。これは、エンジンが最適化できるものであり、配列が作成されないようにできます。

[a, b] = [b, a];

デストラクチャリングを使用して配列を分割できます。

const [first, ...rest] = ['a', 'b', 'c'];
    // first = 'a'; rest = ['b', 'c']

10.10.1 返された配列のデストラクチャリング

一部の組み込みJavaScript操作は配列を返します。デストラクチャリングはそれらを処理するのに役立ちます。

const [all, year, month, day] =
    /^(\d\d\d\d)-(\d\d)-(\d\d)$/
    .exec('2999-12-31');

グループのみに関心があり(完全一致であるallには関心がない場合)、省略記法を使用してインデックス0の配列要素をスキップできます。

const [, year, month, day] =
    /^(\d\d\d\d)-(\d\d)-(\d\d)$/
    .exec('2999-12-31');

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

const [, year, month, day] =
    /^(\d\d\d\d)-(\d\d)-(\d\d)$/
    .exec(someStr) || [];

Array.prototype.split() は配列を返します。したがって、配列ではなく要素に関心がある場合は、デストラクチャリングが役立ちます。

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

10.10.2 返されたオブジェクトのデストラクチャリング

デストラクチャリングは、関数またはメソッドによって返されるオブジェクトからデータを取り出すのにも役立ちます。たとえば、イテレーターメソッドnext()は、donevalueの2つのプロパティを持つオブジェクトを返します。次のコードは、イテレーターiterを使用して配列arrのすべての要素をログ出力します。デストラクチャリングはA行で使用されています。

const arr = ['a', 'b'];
const iter = arr[Symbol.iterator]();
while (true) {
    const {done,value} = iter.next(); // (A)
    if (done) break;
    console.log(value);
}

10.10.3 配列デストラクチャリング可能な値

配列デストラクチャリングは、あらゆる反復可能な値で動作します。これは時々役立ちます。

const [x,y] = new Set().add('a').add('b');
    // x = 'a'; y = 'b'

const [a,b] = 'foo';
    // a = 'f'; b = 'o'

10.10.4 複数の戻り値

複数の戻り値の有用性を見るために、関数ptrueを返す配列aの最初の要素を検索する関数findElement(a, p)を実装してみましょう。問題は、findElement()は何を返すべきかということです。要素自体に関心を持つ場合もあれば、そのインデックスに関心を持つ場合もあれば、両方に関心を持つ場合もあります。次の実装は両方返します。

function findElement(array, predicate) {
    for (const [index, element] 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 };
}

この関数は、[index,element]ペアを反復処理する配列メソッドentries()を使用して、配列arrayのすべての要素を反復処理します(A行)。ペアの部分はデストラクチャリングを使用してアクセスされます。

findElement()を使用してみましょう。

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

いくつかのECMAScript 6機能により、より簡潔なコードを書くことができました。コールバックはアロー関数であり、戻り値はプロパティ値の省略記法を持つオブジェクトパターンを使用してデストラクチャリングされます。

indexelementもプロパティキーを参照しているため、それらを言及する順序は関係ありません。それらを交換しても何も変わりません。

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

インデックスと要素の両方に対応することができました。一方のみに関心がある場合はどうでしょうか?ECMAScript 6のおかげで、実装でも対応できます。そして、単一の戻り値を持つ関数と比較した構文上のオーバーヘッドは最小限です。

const a = [7, 8, 6];

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

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

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

10.11 デストラクチャリングアルゴリズム

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

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

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

10.11.1 アルゴリズム

デストラクチャリング代入は次のようになります。

«pattern» = «value»

patternを使用してvalueからデータを取り出したいと考えています。これを行うためのアルゴリズムを説明します。これは関数型プログラミングではパターンマッチング(略してマッチング)として知られています。このアルゴリズムは、patternvalueに照合し、その過程で変数に代入するデストラクチャリング代入のための演算子(「〜に照合」)を指定します。

«pattern»  «value»

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

例を見てみましょう。

ルール(2c)では、ヘッダーは、少なくとも1つのプロパティと0個以上の残りのプロパティを持つオブジェクトパターンが存在する場合に、このルールが実行されることを意味します。そのパターンは値objに照合されます。このルールの効果は、プロパティ値のパターンがobj.keyに照合され、残りのプロパティがobjに照合されることを続行することです。

ルール(2e)では、ヘッダーは、空のオブジェクトパターン{}が値objに照合される場合にこのルールが実行されることを意味します。その後、行うべきことはありません。

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

デストラクチャリング代入のアルゴリズムのみを示します。デストラクチャリング変数宣言とデストラクチャリングパラメーター定義は同様に機能します。

高度な機能(計算されたプロパティキー、プロパティ値の省略記法、代入ターゲットとしてのオブジェクトプロパティと配列要素)についても扱いません。基本事項のみです。

10.11.1.1 パターン

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

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

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

10.11.1.2 変数
10.11.1.3 オブジェクトパターン
10.11.1.4 配列パターン

配列パターンとイテラブル。配列デストラクチャリングのアルゴリズムは、配列パターンとイテラブルから始まります。

ヘルパー関数

function isIterable(value) {
    return (value !== null
        && typeof value === 'object'
        && typeof value[Symbol.iterator] === 'function');
}

配列要素とイテレータ。アルゴリズムは、パターンの要素(矢印の左側)と、イテラブルから取得されたイテレータ(矢印の右側)を使用して続行されます。

ヘルパー関数

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

10.11.2 アルゴリズムの適用

ECMAScript 6では、呼び出し元がオブジェクトリテラルを使用し、呼び出し先がデストラクチャリングを使用する場合、名前付きパラメータをシミュレートできます。このシミュレーションについては、パラメータ処理に関する章で詳細に説明します。次のコードは例を示しています。関数move1()には、xyという2つの名前付きパラメータがあります。

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

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

しかし、なぜ前のコードスニペットのようにパラメータを定義するのでしょうか?次のようにも完全に合法的なES6コードとして記述できるのに、なぜでしょうか?

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

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

10.11.2.1 背景:マッチングによるパラメータの渡し方

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

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

パラメータabは、次のデストラクチャリングと同様に設定されます。

[a=0, b=0]  [1, 2]
10.11.2.2 move2()の使用

move2()でのデストラクチャリングの動作を調べましょう。

例1。move2()は、次のデストラクチャリングにつながります。

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

左辺の単一の配列要素には、右辺に一致するものがないため、{x,y}はデフォルト値と照合され、右辺のデータとは照合されません(ルール3b、3d)。

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

左辺にはプロパティ値の省略記法が含まれており、これは次の略記です。

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

このデストラクチャリングにより、次の2つの代入が行われます(ルール2c、1)。

x = 0;
y = 0;

例2。関数呼び出しmove2({z:3})を調べましょう。これは次のデストラクチャリングにつながります。

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

インデックス0に配列要素があるため、デフォルト値は無視され、次のステップになります(ルール3d)。

{x, y}  { z: 3 }

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

10.11.2.3 move1()の使用

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

例1: move1()

[{x=0, y=0} = {}]  []

インデックス0に配列要素がないため、デフォルト値を使用します(ルール3d)。

{x=0, y=0}  {}

左辺にはプロパティ値の省略記法が含まれているため、このデストラクチャリングは次のものと同等です。

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

右辺にはプロパティxもプロパティyも一致するものがないため、デフォルト値が使用され、次に次のデストラクチャリングが行われます(ルール2d)。

x  0
y  0

これにより、次の代入が行われます(ルール1)。

x = 0
y = 0

例2: move1({z:3})

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

配列パターンの最初の要素には、右辺に一致するものがあり、その一致を使用してデストラクチャリングを続行します(ルール3d)。

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

例1と同様に、右辺にプロパティxyがないため、デフォルト値が使用されます。

x = 0
y = 0
10.11.2.4 結論

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

次へ: 11. パラメータ処理