Но является ли объект распространяющимся каким-то другим существом, отличным от повторяющегося распространения ?
Да. Распространение собственности вообще не использует итерацию. Это новый первичный синтаксис, семантика времени выполнения которого определяется спецификацией , а не в терминах итераций / итераций:
PropertyDefinition: ... ВыражениеПрисваивание
- Пусть exprValue будет результатом вычисления AssignmentExpression.
- Пусть из значения будет? ПолучитьЗначение (exprValue).
- Пусть исключенные имена будут новым пустым списком.
- Вернуть? 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);
}
То есть это будет работать при одних обстоятельствах, но не при других ...
Ну, это верно для обозначения спреда в целом. Распространение свойств определяется только в инициализаторах объектов и работает только тогда, когда операндом является некоторый объект. (И его аналог, новое обозначение остатка свойства, определено в шаблонах назначения деструктурирования.) Итерируемое распространение определяется только в инициализаторах массива и списках аргументов функции и работает только тогда, когда его операнд является итеративным. (И его аналог, итеративная нотация покоя, определяется в шаблонах назначения деструктурирования, которые создают массивы.)