Большинство из нас имеют дело с Объектами
практически каждый день, и это одна из наиболее часто используемых структур данных. Но немногие из нас могут знать, что можно также управлять поведением свойств объекта или, можно сказать, «взламывать» свойства объектов 😂.
В этом посте мы рассмотрим некоторые внутренние свойства объектов, которые могут помочь в достижении этой цели, а также проведем веселую викторину в конце поста 😉.
Прежде чем мы погрузимся во внутреннюю суть object
, давайте начнем с основ.
- Что такое объекты?
- Настройка поведения свойств объекта
- Object.defineProperty
- Использование
- Дескрипторы данных
- значение
- доступный для записи
- Дескрипторы доступа
- получить
- установить
- Дополнительные атрибуты для дескрипторов
- настраиваемый
- перечисляемый
- Получить дескрипторы существующего объекта?
- Object.getOwnPropertyDescriptor
- Использование
- Время викторины
- Заключительные размышления
Что такое объекты?
Объекты
— это коллекция свойств, где каждое свойство имеет ключ
и значение
.
Объекты могут быть созданы в трех формах👇🏻
-
Нотация
literal
сcurly braces {}
. Это наиболее часто используемый синтаксис. -
Использование конструктора
Object
. КлассObject
представляет собой одну из структур данных вJavascript
. Вряд ли возникнет необходимость использовать эту форму при создании объектов, но все же полезно знать 🙂 . -
Мы не будем вдаваться в подробности о третьей форме, но расскажем о ней позже в этом посте 🙂 .
Настройка поведения свойств объекта
Итак, начать работу с объектами довольно просто, но вот дальше начинается интересный факт — поведение свойств объекта также можно настраивать.
Давайте посмотрим, какие настройки возможны 👀.
Класс Object
имеет статический
метод defineProperty
, который позволяет добавить
новое свойство или обновить
существующее свойство объекта
, а также контролировать поведение свойства. Доступ к статическим
свойствам осуществляется напрямую через класс
, экземпляры не нужно создавать для доступа к статическим
свойствам.
Object.defineProperty
Использование
Object.defineProperty(obj, property, descriptor)
Существует два типа дескрипторов descriptors
.
Дескрипторы данных
Name |
Type |
Default |
Description |
---|---|---|---|
value |
Любой допустимый тип javascript | undefined |
Обозначает значение свойства property . По умолчанию undefined . |
writeable |
boolean |
true |
Подразумевает, может ли значение свойства быть обновлено с помощью оператора присваивания(=) . |
значение
Обозначает значение свойства. По умолчанию undefined
.
var myObj = Object.defineProperty({}, 'id', { value: 1 }); // value is passed
console.log(myObj); // { id: 1 }
myObj = Object.defineProperty({}, 'id', {}); // value not passed
console.log(myObj); // {id: undefined}
доступный для записи
Означает, может ли значение
свойства быть обновлено с помощью
оператора присваивания(=)
. По умолчанию true
.
// writeable will be set to true since not passed
var myObj = Object.defineProperty({}, 'id', { value: 1 });
myObj.id = 10;
myObj.id; // 10
// writeable is false
myObj = Object.defineProperty({}, 'id', { value: 1, writeable: false });
myObj.id = 10;
myObj.id; // 1, as the value couldn't be updated
Дескрипторы доступа
Name |
Type |
Default |
Description |
---|---|---|---|
get |
function |
undefined |
функция , которая возвращает значение свойства. Эта функция вызывается при обращении к свойству. |
set |
function |
undefined |
Функция function , которая устанавливает value свойства property . Эта функция вызывается, когда значение свойства устанавливается с помощью оператора присваивания(=) . |
получить
Функция function
возвращает value
свойства. Эта функция
вызывается, когда доступ к свойству осуществляется с помощью точки(.)
или квадратных скобок([])
.
var myObj = Object.defineProperty({}, 'id', {get: () => 10 });
myObj.id // 10
установить
Функция function
, которая устанавливает value
свойства. Эта функция вызывается, когда значение свойства устанавливается с помощью оператора присваивания(=)
.
var myObj = Object.defineProperty({}, "id", { set: (val) => (id = val) });
myObj.id = 20;
myObj.id = 20;
myObj = Object.defineProperty({}, "id", {
set: (val) => (id = val),
get: () => id,
});
myObj.id = 20;
myObj.id; // 20
Примечание: Объект может иметь либо Data Descriptors
, либо Accessor Descriptors
, но не оба.
myObj = Object.defineProperty({}, 'id', { value: 10, set:() => id = 10 });
// Throws error as we are using both Data and Accessor descriptors
// value is a Data descriptor whereas set is an accessor descriptor
Дополнительные атрибуты для дескрипторов
Помимо data descriptors
и accessor descriptors
, существуют дополнительные атрибуты, общие для обоих дескрипторов👇🏻, которые также могут быть использованы для управления поведением.
Имя | Тип | По умолчанию | Описание |
---|---|---|---|
configurable |
boolean |
false |
Указывает, может ли свойство быть удалено из объекта. |
enumerable |
boolean |
false |
Подразумевает, будет ли свойство отображаться при перечислении ключей объекта. |
настраиваемый
Указывает, можно ли удалить свойство из объекта. По умолчанию false
.
var myObj = Object.defineProperty({}, 'id', { value: 10 });
delete myObj.id
myObj // { id: 10 } as its not configurable
myObj = Object.defineProperty({}, 'id', { value: 10, configurable: true });
delete myObj.id
myObj // {} as its configurable
перечисляемый
Определяет, будет ли свойство отображаться при перечислении
ключей объекта, например, при использовании Object.keys
или for...in
. По умолчанию false
.
var myObj = Object.defineProperty({}, 'id', { value: 10 });
Object.keys(myObj) // [] as the key "id" is not enumerable
myObj = Object.defineProperty({}, 'id', { value: 10, enumerable: true });
Object.keys(myObj) // ["id"] as the key "id" is enumerable
Для обновления многочисленных свойств
можно использовать Object.defineProperties
.
Object.defineProperties(obj, {
property1: descriptor,
property2: descriptor
});
Как упоминалось ранее, существует и третий способ создания объекта - Object.create
, который помогает создать объект с указанным прототипом объекта и дескрипторами.
Теперь, когда вы знаете о дескрипторах
, с помощью которых можно управлять поведением свойств, можете ли вы догадаться, почему 👇🏻 это возможно?
var myObj = { id : 10 };
myObj.id; // 10
myObj.id = 100;
myObj.id; // 100
Object.keys(id); // ["id"];
delete myObj.id
myObj; // {}
Это означает, что когда объекты
создаются с помощью буквальной нотации
/ конструктора Object()
или даже добавляется новое свойство с помощью оператора присваивания(.)
, дескрипторы устанавливаются в 👇🏻.
Имя | Значение |
---|---|
value |
Значение, которое устанавливается при создании / обновлении объекта. |
writeable |
|
enumerable |
|
configurable |
Получить дескрипторы существующего объекта?
Используя дескрипторы
, мы имеем гораздо больше контроля, но должен быть какой-то способ получить дескрипторы свойств существующего объекта. Да, есть статический метод getOwnPropertyDescriptor
в классе Object
, который помогает добиться того же 😍.
Object.getOwnPropertyDescriptor
Использование
Object.getOwnPropertyDescriptor(obj, property)
var myObj = { id: 10 };
Object.getOwnPropertyDescriptor(myObj, 'id')// {value: 10, writable: true, enumerable: true, configurable: true}
Для получения дескрипторов
всех свойств
объекта мы можем использовать Object.getOwnPropertyDescriptors
.
Object.getOwnPropertyDescriptors(obj)
Время викторины
Пришло время провести веселую викторину 😉. Пройдите викторину здесь . Удачи!
Заключительные размышления
Если вы использовали такие методы, как Object.freeze
, Object.sealed
, то теперь вы знаете, что они делают за кулисами 🙂 Они изменяют дескрипторы
для свойств объекта.
В большинстве случаев эти утилиты действительно помогают, но могут быть случаи, когда вы хотите получить больше контроля над свойствами, и тогда вам придется использовать эту утилиту. Надеюсь, вам понравился этот пост 😍.