Object.defineProperty против ванильного свойства

Учитывая базовый сценарий использования, сделайте

foo.bar = 'baz';

а также

Object.defineProperty(foo, 'bar', {
  value: 'baz',
  configurable: true,
  enumerable: true,
  writable: true
});

вести себя точно так же в поддерживаемых браузерах?

Можем ли мы вернуться к ванили в приложениях до ES6 только из-за благоприятного синтаксиса или смешать их оба без каких-либо побочных эффектов?


person Estus Flask    schedule 25.04.2015    source источник
comment
В конце вашего вопроса стоит вопросительный знак, но на самом деле это не вопрос. Не могли бы вы перефразировать вопрос, пожалуйста?   -  person Richard Rout    schedule 25.04.2015
comment
Когда вы определяете свойство без использования defineProperty, obj.property = 'value' и с defineProperty со всеми объектами дескриптора с истинными значениями одинаковы. Но когда вы изменяете свойства объекта дескриптора, такие как настраиваемый, перечисляемый или доступный для записи, оба объявления различаются.   -  person Jagadish Dharanikota    schedule 25.04.2015
comment
В подавляющем большинстве случаев они ведут себя точно так же. Однако существует пограничный случай, если прототип имеет другой дескриптор свойства: Создание новых объектов из замороженных родительских объектов   -  person Qantas 94 Heavy    schedule 25.04.2015
comment
Спасибо всем, господа, это, по сути, то, что я хотел знать.   -  person Estus Flask    schedule 26.04.2015


Ответы (1)


Да, они ведут себя одинаково, когда

  • в foo нет свойства bar (даже унаследованного), поэтому создается новое, или
  • есть свойство bar, для атрибутов writable и configurable которого задано значение true

Однако, если ни один из них не задан, они действительно дают несколько разные результаты.

  • defineProperty не учитывает унаследованные свойства и их дескрипторы
  • Если существующее (возможно, унаследованное) свойство является аксессором, присваивание попытается вызвать установщик (и потерпит неудачу, если его не существует), в то время как definePropery перезапишет свойство дескриптором данных (или потерпит неудачу, если оно является собственным, ненастраиваемым). один)
  • Если существующее унаследованное свойство является свойством данных, присваивание завершится ошибкой, если writable равно false, или создаст новое собственное свойство, если оно истинно, как всегда делает defineProperty
  • Если существующее собственное свойство является свойством данных, присваивание завершится ошибкой, если writable равно false, или установит новое значение, если оно истинно, в то время как defineOwnProperty завершится ошибкой, если configurable равно false, и в противном случае перезапишет атрибуты.

Учитывая базовый сценарий использования

Если под «базовым использованием» вы подразумеваете отсутствие использования причудливых атрибутов свойств, то да, они эквивалентны. Тем не менее, вы должны просто использовать простые присваивания, поскольку их легче читать и быстрее выполнять.

Можем ли мы вернуться к ванили в приложениях до ES6?

Обратите внимание, что полная поддержка defineProperty поставляется с ES5, поэтому, если вам не нужно рассматривать браузеры до ES5 (старый IE), вам все равно.

person Bergi    schedule 25.04.2015
comment
Еще одно требование для того, чтобы вести себя так же, предполагает, что Object является глобальным (не затененным) и ни глобальное Object, ни его свойство defineProperty не были изменены. - person Oriol; 25.04.2015
comment
@Oriol: Да, конечно, я ожидал, что Object.defineProperty будет внутренним методом. - person Bergi; 25.04.2015
comment
Спасибо, Берги, довольно исчерпывающе - person Estus Flask; 26.04.2015