Pull to refresh

Comments 11

Пятый пункт неверен. В JS нет гарантии что свойства в объекте будут хоть как то упорядочены. Это отдано на откуп движку. Эту разницу было хорошо видно в V8 и Rhino. Один сортировал по алфавиту — второй оставлял как есть, не помню который как. На порядок свойств в объекте полагаться НЕЛЬЗЯ! Если нужен доступ по ключу и определенный порядок свойств — используйте Map
UFO just landed and posted this here
Ваши представления устарели минимум на 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 вообще не при делах.

Как она происходит, это понятно. Откуда мысль о его предназначении, о том, что использование его на объекте с прототипом это что-то ужасное?

Sign up to leave a comment.

Articles