10. Destrukcja

10. Destrukcja #

  • 10.1. Przegląd
    • 10.1.1. Niszczenie obiektów
    • 10.1.2. Destrukcja tablicy
    • 10.1.3. Gdzie można użyć destrukcji?
  • 10.2. Tło: konstruowanie danych a wyodrębnianie danych
  • 10.3. Wzorce do destrukcji
    • 10.3.1. Wybierz to, czego potrzebujesz
  • 10.4. Jak wzorce mają dostęp do wnętrzności wartości?
    • 10.4.1. Wzorce obiektów wymuszają wartości dla obiektów
    • 10.4.2. Wzorce tablic działają z iterablami
  • 10.5. Wartości domyślne
    • 10.5.1. undefined wyzwala domyślne wartości
    • 10.5.2. Wartości domyślne są obliczane na żądanie
    • 10.5.3. Wartości domyślne mogą odnosić się do innych zmiennych we wzorze
    • 10.5.4. Domyślne wartości dla wzorców
    • 10.5.5. Bardziej złożone wartości domyślne
  • 10.6. Więcej funkcji niszczenia obiektów
    • 10.6.1. Skróty wartości nieruchomości
    • 10.6.2. Computed Property keys
  • 10.7. Więcej funkcji destrukcji tablicy
    • 10.7.1. Elision
    • 10.7.2. Operator Rest (...)
  • 10.8. Możesz przypisać więcej niż tylko zmienne
  • 10.9. Pułapki destrukcji
    • 10.9.1. Nie zaczynaj wypowiedzi od klamry
  • 10.10. Przykłady destrukcji
    • 10.10.1. Destrukcja zwróconych tablic
    • 10.10.2. Niszczenie zwróconych obiektów
    • 10.10.3. Tablica-destrukcja iterowalnych wartości
    • 10.10.4. Wiele wartości zwracanych
  • 10.11. Algorytm destrukcji
    • 10.11.1. Algorytm
    • 10.11.2. Zastosowanie algorytmu

10.1 przegląd #

destrukcja jest wygodnym sposobem wyodrębniania wielu wartości z danych przechowywanych w (prawdopodobnie zagnieżdżonych) obiektach i tablicach. Może być używany w miejscach, które otrzymują dane (np. po lewej stronie przypisania). Sposób wyodrębniania wartości jest określony za pomocą wzorców (Czytaj dalej, aby zobaczyć przykłady).

10.1.1 niszczenie obiektów #

niszczenie obiektów:

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'

destrukcja pomaga w przetwarzaniu wartości zwrotnych:

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

10.1.2 destrukcja tablicy #

destrukcja tablicy (działa dla wszystkich iteracyjnych wartości):

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

destrukcja pomaga w przetwarzaniu wartości zwrotnych:

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

10.1.3 gdzie można użyć destrukcji? #

destrukcji można użyć w następujących miejscach (pokazuję wzorce tablic do zademonstrowania; wzorce obiektów działają równie dobrze):

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

można również zniszczyć w pętli for-of :

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

10.2 Tło: konstruowanie danych a wyodrębnianie danych #

aby w pełni zrozumieć, czym jest destrukcja, zbadajmy najpierw jego szerszy kontekst.

JavaScript ma operacje na konstruowaniu danych, jedna właściwość na raz:

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

ta sama składnia może być użyta do wyodrębnienia danych. Ponownie, jedna nieruchomość na raz:

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

dodatkowo, istnieje składnia do konstruowania wielu właściwości w tym samym czasie, za pomocą dosłownego obiektu:

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

przed ES6 nie istniał odpowiedni mechanizm ekstrakcji danych. Tym właśnie jest destrukcja-pozwala wyodrębnić wiele właściwości z obiektu za pomocą wzorca obiektu. Na przykład po lewej stronie zadania:

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

można również niszczyć Tablice za pomocą wzorców:

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

10.3 wzory destrukcji #

w destrukcji biorą udział następujące dwie strony:

  • źródło destrukcji: dane, które mają zostać zniszczone. Na przykład po prawej stronie zadania destrukcyjnego.
  • destrukcja celu: wzór używany do destrukcji. Na przykład po lewej stronie zadania destrukcyjnego.

celem destrukcji jest jeden z trzech wzorców:

  • cel zadania. Na przykład: x
    • celem przypisania jest zwykle zmienna. Ale w zadaniu destrukcji masz więcej opcji, jak wyjaśnię później.
  • wzór obiektu. Na przykład: { first: "pattern", last: "pattern" }
    • części wzorca obiektu są właściwościami, wartości właściwości są ponownie wzorcami (rekurencyjnie).
  • wzór tablicy. Na przykład:
    • części wzorca tablicy są elementami, elementy są ponownie wzorcami (rekurencyjnie).

oznacza to, że można zagnieżdżać wzory, dowolnie głęboko:

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

10.3.1 Wybierz to, czego potrzebujesz #

jeśli niszczysz obiekt, wymieniasz tylko te właściwości, które Cię interesują:

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

jeśli zniszczysz tablicę, możesz wyodrębnić tylko prefiks:

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

10.4 jak wzorce mają dostęp do wnętrzności wartości? #

w przypisaniu pattern = someValue, jak patternma dostęp do tego, co znajduje się w środku someValue?

10.4.1 wzorce obiektów wymuszają wartości do obiektów #

wzorce obiektów wymuszają destrukcję źródeł do obiektów przed uzyskaniem dostępu do właściwości. Oznacza to, że działa z prymitywnymi wartościami:

const {length : len} = 'abc'; // len = 3const {toString: s} = 123; // s = Number.prototype.toString
10.4.1.1 brak obiektu-destrukcja wartości #

wymuszenie na obiekcie nie jest wykonywane poprzez Object(), lecz poprzez wewnętrzną operację ToObject(). Obie operacje obsługują undefined i null inaczej.

Object() konwertuje pierwotne wartości na obiekty opakowujące i pozostawia obiekty nietknięte:

> 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

w konsekwencji można użyć wzorca pustego obiektu {}, aby sprawdzić, czy wartość jest wymuszalna dla obiektu. Jak widzieliśmy, tylko undefined i null nie są:

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

nawiasy wokół wyrażeń są konieczne, ponieważ instrukcje nie mogą zaczynać się od nawiasów klamrowych w JavaScript (szczegóły wyjaśniono później).

10.4.2 wzorce tablic działają z iterablami #

destrukcja tablicy używa iteratora, aby dostać się do elementów źródła. Dlatego możesz zniszczyć dowolną wartość, która jest iterowalna. Spójrzmy na przykłady wartości iteracyjnych.

ciągi są iterowalne:

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

nie zapominaj, że iterator nad łańcuchami zwraca punkty kodu („znaki Unicode”, 21 bitów), a nie jednostki kodu („znaki JavaScript”, 16 bitów). (Aby uzyskać więcej informacji na temat Unicode, zapoznaj się z rozdziałem ” Rozdział 24. Unicode i JavaScript ” w „Speaking JavaScript”.) Na przykład:

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

nie można uzyskać dostępu do elementów zestawu za pomocą indeksów, ale można to zrobić za pomocą iteratora. Dlatego destrukcja tablic działa dla zestawów:

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

iterator Set zawsze zwraca elementy w kolejności, w jakiej zostały wstawione, dlatego wynik poprzedniego destrukcji jest zawsze taki sam.

10.4.2.1 brak destrukcji tablicy wartość #

wartość jest iterowalna, jeśli posiada metodę, której kluczem jest Symbol.iterator, która zwraca obiekt. Array-destructing wyrzuca TypeError, jeśli wartość do zniszczenia nie jest iteracyjna:

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 jest wyrzucany jeszcze przed dostępem do elementów iterowalnych, co oznacza, że możesz użyć pustego wzorca tablicy , aby sprawdzić, czy wartość jest iterowalna:

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

10.5 wartości domyślne #

wartości domyślne są opcjonalną funkcją wzorców. Stanowią one rezerwę, jeśli nic nie zostanie znalezione w źródle. Jeśli część (właściwość obiektu lub element tablicy) nie ma dopasowania w źródle, jest dopasowywana do:

  • jego wartość domyślna (jeśli podano; jest opcjonalny)
  • undefined (inaczej)

spójrzmy na przykład. W poniższej destrukcji element o indeksie 0 nie ma dopasowania po prawej stronie. Dlatego destrukcja jest kontynuowana przez dopasowanie x do 3, co prowadzi do Ustawienia x na 3.

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

można również używać wartości domyślnych we wzorcach obiektów:

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

10.5.1 undefined wyzwalacze domyślne wartości #

domyślne wartości są również używane, jeśli część ma dopasowanie i to dopasowanie jest undefined:

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

uzasadnienie tego zachowania jest wyjaśnione w następnym rozdziale, w sekcji o wartościach domyślnych parametrów.

10.5.2 wartości domyślne są obliczane na żądanie #

same wartości domyślne są obliczane tylko wtedy, gdy są potrzebne. Innymi słowy, owa destrukcja:

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

jest równoważne:

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

można zauważyć, że jeśli używasz 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

liczy się jednak kolejność: zmienne x i y są deklarowane od lewej do prawej i tworzą ReferenceError, jeśli są dostępne przed ich deklaracjami:

const  = ; // ReferenceError

10.5.4 domyślne wartości dla wzorców #

do tej pory widzieliśmy tylko domyślne wartości dla zmiennych, ale można je również skojarzyć z wzorcami:

const  = ;

Co to znaczy? Przypomnij regułę dla wartości domyślnych: jeśli część nie ma dopasowania w źródle, destrukcja jest kontynuowana z wartością domyślną.

element o indeksie 0 nie ma dopasowania, dlatego destrukcja trwa nadal z:

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

możesz łatwiej zobaczyć, dlaczego wszystko działa w ten sposób, jeśli zastąpisz wzorzec { prop: x } zmienną pattern:

const  = ;

10.5.5 bardziej złożone wartości domyślne #

przyjrzyjmy się dalej wartościom domyślnym wzorców. W poniższym przykładzie przypisujemy wartość x poprzez wartość domyślną { prop: 123 }:

const  = ;

ponieważ element tablicy o indeksie 0 nie ma dopasowania po prawej stronie, destrukcja przebiega następująco i x jest ustawiona na 123.

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

jednak x nie jest przypisana w ten sposób wartość, jeśli po prawej stronie znajduje się element o indeksie 0, ponieważ wtedy wartość domyślna nie jest wyzwalana.

const  = ;

w tym przypadku destrukcja jest kontynuowana z:

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

Tak więc, jeśli chcesz, aby x miał wartość 123, jeśli brakuje obiektu lub właściwości, musisz określić domyślną wartość dla samej wartości x :

const  = ;

tutaj destrukcja przebiega następująco, niezależnie od tego, czy prawa strona jest czy .

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

10.6 więcej funkcji destrukcji obiektów #

10.6.1 skróty wartości właściwości #

skróty wartości właściwości są cechą literałów obiektów: Jeśli wartość właściwości jest zmienną o tej samej nazwie co klucz właściwości, to można pominąć klucz. Działa to również na destrukcję:

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

można również łączyć skróty wartości właściwości z wartościami domyślnymi:

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

10.6.2 Computed property keys #

Computed property keys to kolejna literalna funkcja obiektu, która działa również przy destrukcji. Klucz właściwości można określić za pomocą wyrażenia, jeśli umieścimy go w nawiasach kwadratowych:

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

Computed property keys pozwalają niszczyć właściwości, których klucze są symbolami:

// 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 więcej funkcji destrukcji tablicy #

10.7.1 Elision #

Elision pozwala używać składni „dziur” tablicy do pomijania elementów podczas destrukcji:

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

10.7.2 Operator Rest (...) #

operator rest pozwala wyodrębnić pozostałe elementy iteracyjne do tablicy. Jeśli ten operator jest używany wewnątrz wzorca tablicy, musi być ostatni:

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

jeśli operator nie może znaleźć żadnych elementów, dopasowuje swój argument do pustej tablicy. Oznacza to, że nigdy nie produkuje undefined lub null. Na przykład:

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

operand operatora rest nie musi być zmienną, można też użyć wzorców:

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

Operator rest uruchamia następujące destrukcje:

 = 

10.8 możesz przypisać więcej niż tylko zmienne #

jeśli przypisujesz poprzez destrukcję, każdy cel przypisania może być wszystkim, co jest dozwolone po lewej stronie normalnego przypisania.

na przykład odwołanie do właściwości (obj.prop):

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

lub odniesienie do elementu tablicy(arr):

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

można również przypisać do Właściwości obiektu i elementów tablicy za pomocą operatora rest (...):

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

jeśli deklarujesz zmienne lub definiujesz parametry poprzez destrukcję, musisz użyć prostych identyfikatorów, nie możesz odwoływać się do Właściwości obiektu i elementów tablicy.

10.9 pułapki destrukcji #

przy użyciu destrukcji należy pamiętać o dwóch rzeczach:

  • nie możesz zacząć zeznań od klamry.
  • podczas destrukcji możesz zadeklarować zmienne lub przypisać do nich, ale nie obie.

kolejne dwie sekcje zawierają szczegóły.

10.9.1 nie rozpoczynaj instrukcji nawiasem klamrowym #

ponieważ bloki kodu zaczynają się nawiasem klamrowym, polecenia nie mogą zaczynać się od jednego. Jest to niefortunne w przypadku korzystania z destrukcji obiektów w przypisaniu:

{ a, b } = someObject; // SyntaxError

obejście polega na umieszczeniu pełnego wyrażenia w nawiasach:

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

nie działa następująca składnia:

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

z let, var i const kręcone szelki nigdy nie powodują problemów:

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

10.10 przykładów destrukcji #

Zacznijmy od kilku mniejszych przykładów.

pętla for-of obsługuje destrukcję:

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

możesz użyć destrukcji do zamiany wartości. To jest coś, co silniki mogą zoptymalizować, tak, że nie zostanie utworzona tablica.

 = ;

możesz użyć destrukcji, aby podzielić tablicę:

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

10.10.1 destrukcja zwróconych tablic #

niektóre wbudowane operacje JavaScript zwracają Tablice. Destrukcja pomaga w ich przetwarzaniu:

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

jeśli jesteś zainteresowany tylko grupami (a nie kompletnym dopasowaniem, all), możesz użyć elision, aby pominąć element tablicy w indeksie 0:

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

exec() zwraca null, jeśli wyrażenie regularne nie jest zgodne. Niestety, nie możesz obsłużyć null za pomocą wartości domyślnych, dlatego w tym przypadku musisz użyć operatora Or (||) :

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

Array.prototype.split() zwraca tablicę. Dlatego destrukcja jest przydatna, jeśli interesują Cię elementy, a nie tablica:

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

10.10.2 destrukcja zwracanych obiektów #

destrukcja jest również przydatna do wyciągania danych z obiektów, które są zwracane przez funkcje lub metody. Na przykład metoda iteratora next() zwraca obiekt o dwóch właściwościach, donei value. Poniższy kod rejestruje wszystkie elementy tablicy arr poprzez iterator iter. W linii A stosuje się destrukcję.

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

10.10.3 array-destructing wartości iteratywne #

array-destructing działa z dowolną wartością iteratywną. To jest czasami przydatne:

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

10.10.4 wiele zwracanych wartości #

aby zobaczyć użyteczność wielu zwracanych wartości, zaimplementujmy funkcję findElement(a, p), która wyszukuje pierwszy element w tablicy a, dla którego funkcja p zwraca true. Pytanie brzmi: co należy zwrócić findElement()? Czasem interesuje nas sam element, czasem jego indeks, czasem jedno i drugie. Następująca implementacja zwraca oba.

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 };}

funkcja iteruje nad wszystkimi elementami array, za pomocą metody Array entries(), która zwraca iterowalną nad parami (linia A). Części par są dostępne poprzez destrukcję.

użyjmy findElement():

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

kilka funkcji ECMAScript 6 pozwoliło nam napisać bardziej zwięzły kod: wywołanie zwrotne jest funkcją strzałki; wartość zwracana jest niszczona za pomocą wzorca obiektu ze skróconymi wartościami właściwości.

ze względu na index i element również odnoszące się do kluczy właściwości, kolejność, w jakiej je wspominamy, nie ma znaczenia. Możemy je zamienić i nic się nie zmienia:

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

z powodzeniem obsłużyliśmy przypadek konieczności zarówno indeksu, jak i elementu. Co jeśli interesuje nas tylko jeden z nich? Okazuje się, że dzięki ECMAScript 6 nasza implementacja może się tym zająć. A narzut składniowy w porównaniu z funkcjami z pojedynczymi wartościami zwracanymi jest minimalny.

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

za każdym razem wyodrębniamy tylko wartość jednej właściwości, której potrzebujemy.

10.11 algorytm destrukcji #

Ta sekcja patrzy na destrukcję pod innym kątem: jako rekurencyjny algorytm dopasowywania wzorców.

na końcu użyję algorytmu, aby wyjaśnić różnicę między następującymi dwiema deklaracjami funkcji.

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

10.11.1 algorytm #

zadanie destrukcyjne wygląda tak:

"pattern" = "value"

chcemy użyć pattern, aby wyodrębnić dane z value. Opiszę teraz algorytm, który jest znany w programowaniu funkcyjnym jako pattern matching (w skrócie: dopasowanie). Algorytm określa operatora („match against”) dla destrukcyjnego przypisania, który dopasowuje pattern do value i przyporządkowuje zmienne podczas tego procesu:

"pattern"  "value"

algorytm jest określony za pomocą reguł rekurencyjnych, które rozdzielają oba operandy operatora . Notacja deklaratywna może zająć trochę czasu, ale sprawia, że specyfikacja algorytmu jest bardziej zwięzła. Każda reguła składa się z dwóch części:

  • head (pierwsza linia) opisuje warunek, który wyzwala regułę.
  • ciało (pozostałe linie) opisuje, co się stanie, jeśli reguła zostanie wywołana.

spójrzmy na przykład:

  • (2c) {key: "pattern", "properties"} ← obj
     "pattern"  obj.key {"properties"}  obj
  • (2e) {} ← obj (brak obiektów)
     // Nothing to do

w rule (2C), head oznacza, że ta reguła jest wykonywana, jeśli istnieje wzorzec obiektu z co najmniej jedną właściwością i zero lub więcej pozostałych właściwości. Ten wzorzec jest dopasowywany do wartości obj. Efekt tej reguły jest taki, że wykonanie jest kontynuowane przy dopasowaniu wzorca wartości właściwości do obj.key, a pozostałych właściwości do obj.

w rule (2e), head oznacza, że ta reguła jest wykonywana, jeśli pusty wzorzec obiektu {} jest dopasowany do wartości obj. Więc nic nie można zrobić.

za każdym razem, gdy algorytm jest wywoływany, reguły są sprawdzane od góry do dołu i wykonywana jest tylko pierwsza reguła, która ma zastosowanie.

pokazuję tylko algorytm destrukcji. Podobnie działają deklaracje zmiennych destrukcyjnych i definicje parametrów destrukcyjnych.

nie zajmuję się zaawansowanymi funkcjami (computed property keys; property value shorthands; właściwości obiektu i elementy tablicy jako cele przypisania). Tylko podstawy.

10.11.1.1 wzory #

wzór jest albo:

  • zmienna: x
  • wzór obiektu: {"properties"}
  • wzór tablicy:

każda z poniższych sekcji opisuje jeden z tych trzech przypadków.

poniższe trzy sekcje określają sposób postępowania z tymi trzema przypadkami. Każda sekcja zawiera jedną lub więcej ponumerowanych reguł.

10.11.1.2 zmienne #
  • (1) x ← value (w tym undefined i null)
     x = value
10.11.1.3 wzór obiektu #
  • (2a) {"properties"} ← undefined
     throw new TypeError();
  • (2b) {"properties"} ← null
     throw new TypeError();
  • (2c) {key: "pattern", "properties"} ← obj
     "pattern"  obj.key {"properties"}  obj
  • (2d) {key: "pattern" = default_value, "properties"} ← obj
     const tmp = obj.key; if (tmp !== undefined) { "pattern"  tmp } else { "pattern"  default_value } {"properties"}  obj
  • (2e) {} ← obj (brak obiektów)
     // Nothing to do
10.11.1.4 wzór tablicy #

wzór tablicy i iteracyjny. Algorytm destrukcji tablicy zaczyna się od wzorca tablicy i iteracyjnego:

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

funkcja pomocnicza:

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

elementy tablicy i iterator. Algorytm kontynuuje elementy wzorca (po lewej stronie Strzałki) i iteratora, który został uzyskany z iterable (po prawej stronie strzałki).

  • (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(hole, elision)
     getNext(iterator); // skip "elements"  iterator
  • (3f) ..."pattern" ← iterator(zawsze ostatnia część!)
     const tmp = ; for (const elem of iterator) { tmp.push(elem); } "pattern"  tmp
  • (3g) ← iterator (brak elementów)
     // Nothing to do

funkcja pomocnicza:

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

10.11.2 stosując algorytm #

w ECMAScript 6, można symulować nazwane parametry, jeśli wywołujący używa dosłownego obiektu, a wywołujący używa destrukcji. Ta symulacja została szczegółowo wyjaśniona w rozdziale dotyczącym obsługi parametrów. Poniższy kod pokazuje przykład: funkcja move1() ma dwa nazwane parametry, x i y:

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

w wierszu A są trzy wartości domyślne:

  • pierwsze dwie wartości domyślne pozwalają pominąć xi y.
  • trzecia wartość domyślna pozwala na wywołanie move1() bez parametrów (jak w ostatniej linii).

ale dlaczego mielibyście zdefiniować parametry jak w poprzednim fragmencie kodu? Dlaczego nie w następujący sposób-który jest również całkowicie legalny kod ES6?

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

aby zobaczyć, dlaczego move1() jest poprawne, użyjmy obu funkcji dla dwóch przykładów. Zanim to zrobimy, zobaczmy, jak przekazywanie parametrów może być wyjaśnione poprzez dopasowanie.

10.11.2.1 Tło: przekazywanie parametrów poprzez dopasowanie #

dla wywołań funkcji, formalne parametry (wewnątrz definicji funkcji) są dopasowywane do rzeczywistych parametrów (wewnątrz wywołań funkcji). Jako przykład, weź następującą definicję funkcji i następujące wywołanie funkcji.

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

parametry a i bsą ustawione podobnie do następującej destrukcji.

  
10.11.2.2 używanie move2() #

sprawdźmy, jak działa destrukcja dla move2().

przykład 1. move2() prowadzi do tego zniszczenia:

  

pojedynczy element tablicy po lewej stronie nie ma dopasowania po prawej stronie, dlatego {x,y} jest dopasowany do wartości domyślnej, a nie do danych z prawej strony (reguły 3b, 3d) :

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

lewa strona zawiera skróty wartości właściwości, jest to skrót dla:

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

destrukcja ta prowadzi do następujących dwóch zadań (Zasady 2c, 1):

x = 0;y = 0;

przykład 2. Przyjrzyjmy się wywołaniu funkcji move2({z:3}), które prowadzi do następującej destrukcji:

  

po prawej stronie znajduje się element tablicy o indeksie 0. Dlatego wartość domyślna jest ignorowana, a następnym krokiem jest (reguła 3d):

{x, y}  { z: 3 }

to prowadzi do tego, że zarówno x, jak i y są ustawione na undefined, co nie jest tym, czego chcemy.

10.11.2.3move1() #

spróbujmy move1().

przykład 1: move1()

  

nie mamy elementu tablicy o indeksie 0 po prawej stronie i używamy wartości domyślnej (reguła 3d):

{x=0, y=0}  {}

lewa strona zawiera skróty wartości właściwości, co oznacza, że destrukcja ta jest równoważna:

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

ani własność x, ani własność y nie mają dopasowania po prawej stronie. Dlatego używane są wartości domyślne i następująca destrukcja jest wykonywana dalej (reguła 2d):

x  0y  0

prowadzi to do następujących zadań (zasada 1):

x = 0y = 0

przykład 2: move1({z:3})

  

pierwszy element wzorca tablicy ma dopasowanie po prawej stronie i to dopasowanie jest używane do kontynuowania destrukcji (zasada 3d):

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

podobnie jak w przykładzie 1, po prawej stronie nie ma właściwości x i y i używane są wartości domyślne:

x = 0y = 0
10.11.2.4 wniosek #

przykłady pokazują, że wartości domyślne są cechą części wzorca (właściwości obiektu lub elementów tablicy). Jeśli część nie ma dopasowania lub jest dopasowana do undefined, to używana jest wartość domyślna. Oznacza to, że wzorzec jest dopasowywany do wartości domyślnej.