Защита объекта от изменения в JavaScript
JavaScript

Защита объекта от изменения в JavaScript

Все объекты в JavaScript имеют три атрибута: prototype, class и extensible. В данной статье мы поговорим об атрибуте extensible, как с его помощью и с помощью атрибутов свойств можно защитить объект от изменения.

Атрибут extensible

Атрибут объекта extensible в JavaScript позволяет определить, разрешено ли добавлять новые свойства к данному объекту. В спецификации ECMAScript 3 все пользовательские и встроенные объекты являются по умолчанию расширяемыми. В ECMAScript 5 они также являются расширяемыми, однако спецификация позволяет изменить атрибут extensible объекта.

Комбинации атрибутов свойств writable и configurable и атрибута extensible объекта формируют три уровня защиты объекта от изменений:

  • Preventing extensions
  • Sealing
  • Freezing

Preventing extensions

Первый уровень защиты объекта от изменений — сделать его нерасширяемым. Для этого необходимо установить значение атрибута extensible равное false. Проверить, является ли объект расширяемым, можно с помощью метода Object.isExtensible(). Сделать объект нерасширяемым можно с помощью метода Object.preventExtensions().


var book = { title: 'Alice in Wonderland' };
Object.preventExtensions(book);
book.author = 'Lewis Carroll';
console.log(book.author); //undefined

В строгом режиме (strict mode) в примере выше мы получим исключение:


TypeError: ({ title: 'Alice in Wonderland' }) is not extensible

При этом мы спокойно можем удалять уже существующие свойства:


delete book.title;
console.log(book.title); // undefined

Sealing

Второй уровень защиты объекта от изменения: сделать его нерасширяемым, а все его свойства неконфигурируемыми. Для этого используется метод Object.seal().

Рассмотрим пример:


var book = { title: 'Alice in Wonderland' };

// выведем дескриптор свойства до вызова метода Object.seal()
console.log(Object.getOwnPropertyDescriptor(book, 'title'));
Object.seal(book);

// выведем дескриптор свойства после вызова метода Object.seal()
console.log(Object.getOwnPropertyDescriptor(book, 'title'));

// является ли объект расширяемым
console.log(Object.isExtensible(book));

В примере выше мы можем убедиться, что метод Object.seal() не только делает объект нерасширяемым, но и устанавливает атрибут configurable всех свойств объекта равным false.

Мы по прежнему можем изменять значения свойств объекта, но если захотим удалить или изменить атрибуты свойств — получим исключение:


Object.defineProperty(book, 'title', { enumerable: false });
// TypeError: can't redefine non-configurable property 'title'

Проверить, является ли объект «запечатанным», можно с помощью метода Object.isSealed(obj).

Freezing

Наконец, третий уровень защиты объекта от изменений не только делает объект нерасширяемым, а все его свойства неконфигурируемыми — он также запрещает изменять значения свойств, устанавливая атрибут writable все свойств равным false. «Заморозить» объект можно с помощью метода Object.freeze().

Рассмотрим пример:


var point = { x: 17, y: -5 };
Object.freeze(point);

point.x = 25;
console.log(point.x); // 17

В строгом режиме в примере выше мы получим исключение:


TypeError: "x" is read-only

Проверить, является ли объект «замороженным», можно с помощью метода Object.isFrozen().

Обратите внимание, что способы защиты объекта влияют на сам объект и на его собственные свойства, но не на значения свойств. Например:


var obj = {
    foo: 1,
    bar: ['a', 'b']
};
Object.freeze(obj);

obj.bar.push('c');
console.log(obj); // Object { foo=1, bar=['a', 'b', 'c']}

Заключение

В статье мы рассмотрели методы защиты объектов от изменения, предусмотренные в спецификации ECMAScript 5.

Метод Object.preventExtensions() позволяет сделать объект нерасширяемым, метод Object.seal() делает объект нерасширяемым, одновременно делает неконфигурируемыми все свойства объекта, и наконец, метод Object.freeze() полностью “замораживает” объект: делает его нерасширяемым, а все его свойства неконфигурируемыми и не доступными для записи.

При использовании методов защиты объектов следует иметь в виду, что они оказывают влияние на объект и его собственные свойства, но не влияют на значения свойств объекта и на его унаследованные свойства.

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться