Comments 11
Пятый пункт неверен. В JS нет гарантии что свойства в объекте будут хоть как то упорядочены. Это отдано на откуп движку. Эту разницу было хорошо видно в V8 и Rhino. Один сортировал по алфавиту — второй оставлял как есть, не помню который как. На порядок свойств в объекте полагаться НЕЛЬЗЯ! Если нужен доступ по ключу и определенный порядок свойств — используйте Map
Ваши представления устарели минимум на 5 лет. Начиная с ES2015, порядок свойств в объекте (а точнее, работа всех методов, так или иначе выдающих список ключей) гарантируется стандартом: строковые и прочие свойства всегда упорядочены в хронологическом порядке (как объявляли, так и будет), а натуральные (целочисленные 0-inf, например {0: «foo»}) — отсортированы по возрастанию от нуля и идут перед прочими.
В примере ниже деструктуризуем объект rest и убираем из него свойство password.
const noPassword = ({ password, ...rest }) => rest
Хе-хе. Не «убираем», а создаём рядом новый объект, в который копируем все enumerable-ключи, кроме password. И не копируем при этом дескрипторы и всё скрытое.
А потом удивляемся, почему всё тормозит, и vue/react/etc неправильно работает…
Какие дескрипторы? Что скрытое? Все описанное относится к объектам с не переопределенным prototype. Ко всему прочему спреад в основном используется для immutable операциях, в которых важна трудоемкость сравнения а не модификации… Это отличный инструмент для своих целей, и если цели не совпадают — то не нужно хаять не подходящий инструмент.
const noPassword = ({ password, ...rest }) => rest;
let user1 = {
name: "John",
surname: "WTF!!!",
get fullName() { return `${this.name} ${this.surname}`; },
set setFullName(value) { [this.name, this.surname] = value.split(" "); },
password: "password",
};
// Запрещаем менять поле name
Object.defineProperty(user1, "name", {writable: false});
// «Удаляем» password
let user2 = noPassword(user1);
user1.name = 'WTF!!!';
user2.name = 'WTF!!!';
console.log(user1.name, 'vs', user2.name);
// John vs WTF!!!
// Ха-ха, десткриптор writable: false продолбан
user1.surname = 'Smith';
user2.surname = 'Smith';
console.log(user1.fullName, 'vs', user2.fullName);
// John Smith vs John WTF!!!
// Ха-ха, getter превратился в атрибут
user1.setFullName = 'John Blah';
user2.setFullName = 'John Blah';
console.log(JSON.stringify(user1), '\nvs\n', JSON.stringify(user2));
// {"name":"John","surname":"Blah","fullName":"John Blah","password":"password"}
// vs
// {"name":"WTF!!!","surname":"Smith","fullName":"John WTF!!!","setFullName":"John Blah"}
// Ха-ха, сеттер вообще продолбан :)
delete user1.password
console.log(JSON.stringify(user1))
// {"name":"John","surname":"Blah","fullName":"John Blah"}
// Если нужно было именно удалить свойство, а не создать новый объект
Это отличный инструмент для своих целей, и если цели не совпадают — то не нужно хаять не подходящий инструмент.
Да-да, вы абсолютно правы. Если цель — создать новый объект, в который скопированы все enumerable-ключи, кроме password, но не скопированы дескрипторы, то да.
Но нужно быть осторожным в реактивных фреймворках, где всё на геттерах-сеттерах.
А можно ссылку на спеку или какие-то разъяснения от ее разработчиков, что спреад именно предназначен для работы с объектами с не переопределенным prototype? А не просто, что есть вот такое его функционирование, где подходит, там и используйте
sec-object-initializer
propertydefinitionevaluation
copydataproperties
ownpropertykeys
Если забить на некоторые тонкости с null'ами, underfind'ами и прочие тонкости, то добыча атрибутов в spread происходит так.
Cоставляем список претендентов на копирование:
сначала в порядке возрастания own property, которые являются числами; потом в хронологическом порядке ключи-строки, потом в хронологическом порядке ключи-символы.
Дальше для каждого ключа-претендента сделать [[GetOwnProperty]]. Если у результата [[Enumerable]]=true, то скопировать ключ. Что такое «скопировать». Для этого используется [[Get]]
get-p-receiver
Так как выше в претенденты добавлены только собственные ключи, то прототайпы курят в сторонке. Если значения ключа имеет value или дескриптор writable, то возвращается оно. Иначе это — геттер, и возвращается то, что вернёт геттер.
Судя по спеке, prototype вообще не при делах.
propertydefinitionevaluation
copydataproperties
ownpropertykeys
Если забить на некоторые тонкости с null'ами, underfind'ами и прочие тонкости, то добыча атрибутов в spread происходит так.
Cоставляем список претендентов на копирование:
сначала в порядке возрастания own property, которые являются числами; потом в хронологическом порядке ключи-строки, потом в хронологическом порядке ключи-символы.
Дальше для каждого ключа-претендента сделать [[GetOwnProperty]]. Если у результата [[Enumerable]]=true, то скопировать ключ. Что такое «скопировать». Для этого используется [[Get]]
get-p-receiver
Так как выше в претенденты добавлены только собственные ключи, то прототайпы курят в сторонке. Если значения ключа имеет value или дескриптор writable, то возвращается оно. Иначе это — геттер, и возвращается то, что вернёт геттер.
Судя по спеке, prototype вообще не при делах.
Sign up to leave a comment.
7 трюков с Rest и Spread операторами при работе c JS объектами