Как работает распространение объекта, если оно не повторяемое? - PullRequest
0 голосов
/ 28 июня 2018

Я узнаю о новых применениях распространения . Я понимаю, что распространение объекта является предложением ES2018. Он работает в Узле 10.5 следующим образом:

const oldObj = {name:"doug", age:34};
const newObj = {...oldObj}; 
console.log(newObj); // { name: 'doug', age: 34 }

Одним из интересных способов использования распространения является преобразование итераций в массивы. Например, он хорошо работает с картами, предоставляя массив массивов пар значений

const mappie = new Map().set("name", "doug").set("age", 234).set("profession", "seeker of Cthulhu");

const arr1 = [...mappie];

console.log(arr1); // [ [ 'name', 'doug' ], [ 'age', 234 ], [ 'profession', 'seeker of Cthulhu' ] ]

Но я не могу использовать это на объекте

const obj = {
  name: "doug",
  age: 234,
  profession: "seeker of Chthulhu"
};

const arr2 = [...obj];
console.log(arr2);

дает мне

TypeError: obj is not iterable

Хорошо, я понимаю, что объект не повторяется (на данный момент). Но разве объект распространения является каким-то другим существом, отличным от повторяющегося распространения ? То есть это будет работать в некоторых обстоятельствах, но не в других, и нужно просто понимать, что объекты могут распространяться только на объекты, а вы не можете распространять их в массивы? Или я скучаю по большой картине? Я пытаюсь понять новое использование распространения , и любое просвещение приветствуется ....

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

T.J. Ответ Краудера верен, но это слишком долго для комментария и, надеюсь, даст вам лучшее понимание утилиты: рассмотрите частый случай, когда вам требуется пара свойств объекта, и поместите их в новый объект. Несколько сторонних библиотек, таких как Ramda и lodash, реализуют вспомогательные функции, которые делают это, но с помощью комбинации сокращенных свойств, деструктуризации и распространения объектов это можно сделать кратко в vanilla JS:

const foo = { a: 1, b: 2, c: 3, d: 4 };
const { a, d } = foo;
const bar = { a, d };
console.log(bar); // { a: 1, d: 4 }

Если вы не против злоупотребления оператором запятой, вы можете сократить это еще больше:

let a, d, bar, foo = { a: 1, b: 2, c: 3, d: 4 };
bar = ({a, d} = foo, {a, d});
0 голосов
/ 28 июня 2018

Но является ли объект распространяющимся каким-то другим существом, отличным от повторяющегося распространения ?

Да. Распространение собственности вообще не использует итерацию. Это новый первичный синтаксис, семантика времени выполнения которого определяется спецификацией , а не в терминах итераций / итераций:

PropertyDefinition: ... ВыражениеПрисваивание

  1. Пусть exprValue будет результатом вычисления AssignmentExpression.
  2. Пусть из значения будет? ПолучитьЗначение (exprValue).
  3. Пусть исключенные имена будут новым пустым списком.
  4. Вернуть? CopyDataProperties (объект, fromValue, исключенные имена).

Распределение свойств специально для свойств объекта, его нет дополнительного обобщения, как с повторяющимся распространением. (И не сразу видно, как будет. :-))

Для вашего const arr2 = [...obj]; варианта использования вы, вероятно, захотите Object.entries:

const arr2 = Object.entries(obj);

Пример:

const obj = {
  name: "doug",
  age: 234,
  profession: "seeker of Chthulhu"
};
const arr2 = Object.entries(obj);
console.log(arr2);

... или Object.keys, если вам просто нужны имена свойств, или Object.values, если вы просто хотите значения.

Конечно, вы можете сделать объект итеративным, если хотите: просто дайте ему итератор. Например:

const obj = {
  name: "doug",
  age: 234,
  profession: "seeker of Chthulhu",
  * [Symbol.iterator]() {
    return yield* Object.entries(this);
  }
};
const arr2 = [...obj];
console.log(arr2);

И вы можете создавать экземпляры любых классов, которые вы создаете итеративно, определяя соответствующий итератор для них и предоставляя свойство с именем Symbol.iterator для прототипа:

class ExampleList {
    constructor() {
        this.head = this.tail = null;
    }

    add(value) {
        const entry = {value, next: null};
        if (!this.tail) {
            this.head = this.tail = entry;
        } else {
            this.tail = this.tail.next = entry;
        }
    }

    * [Symbol.iterator]() {
        for (let current = this.head; current; current = current.next) {
            yield current.value;
        }
    }
}

const list = new ExampleList();
list.add("a");
list.add("b");
list.add("c");

for (const value of list) {
    console.log(value);
}

То есть это будет работать при одних обстоятельствах, но не при других ...

Ну, это верно для обозначения спреда в целом. Распространение свойств определяется только в инициализаторах объектов и работает только тогда, когда операндом является некоторый объект. (И его аналог, новое обозначение остатка свойства, определено в шаблонах назначения деструктурирования.) Итерируемое распространение определяется только в инициализаторах массива и списках аргументов функции и работает только тогда, когда его операнд является итеративным. (И его аналог, итеративная нотация покоя, определяется в шаблонах назначения деструктурирования, которые создают массивы.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...