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

Это следующие способы создания объектов в Javascript:

Создайте объект с литералом объекта,

'use strict'
var cat = {name: 'blacky', color: 'black'}
console.log(cat)

Вывод:

{name: "blacky", color: "black"}

Создайте объект с помощью функции-конструктора с ключевым словом new, и это позволит нам создать несколько экземпляров с той же структурой объекта, что и класс на языке со статической типизацией,

'use strict'
function Cat() {
  this.name = "blacky";
  this.color = "black";
}
var cat = new Cat();
console.log(cat);

Вывод:

Cat {name: "blacky", color: "black"}

До сих пор мы видели два способа (литерал объекта и функция-конструктор с ключевым словом new) для создания объекта. На самом деле они являются синтаксическим сахаром для object.create . Мы могли бы создать такой же объект, используя object.create. Мы передаем Object.prototype, который станет прототипом вновь созданного объекта. Вы можете видеть, что мы создаем свойства имени и цвета. И для каждого мы присваиваем значение и устанавливаем перечисляемый, записываемый и настраиваемый. Все это происходит, когда мы создаем с использованием двух вышеуказанных методов.

'use strict'
var cat = Object.create(Object.prototype, 
{
    name:{
        value: 'blacky',
        enumerable: true,
        writable: true,
        configurable: true
    },
    color:{
        value: 'black',
        enumerable: true,
        writable: true,
        configurable: true
    }
})
console.log(cat)

Вывод:

{name: "blacky", color: "black"}

ES6 предоставляет функциональность для создания объектов с использованием класса так же, как и в языке со статической типизацией. Опять же, это просто синтаксический сахар поверх существующей функциональности создания объектов. Таким образом, мы могли бы создать тот же объект, используя класс,

'use strict'
class Cat {
    constructor(name, color) {
        this.name = name
        this.color = color
    }
}
var cat = new Cat('blacky', 'black')
console.log(cat)

Вывод:

Cat {name: "blacky", color: "black"}

Итак, теперь мы увидим свойства объекта. Вы можете быть удивлены тем, что свойство — это больше, чем просто имя и значение. Каждое свойство имеет дескриптор свойства, и с его помощью мы можем видеть атрибуты свойства.

Для простоты мы используем здесь объектный литерал,

'use strict'
var cat = { name: 'blacky', color: 'black'}
console.log(Object.getOwnPropertyDescriptor(cat, 'name'))

Вывод:

{value: "blacky", writable: true, enumerable: true, configurable: true}

В выводе мы видим доступные для записи, перечисляемые и настраиваемые атрибуты, которые мы использовали ранее для создания объекта с помощью метода object.create. Так что же это?

Атрибут writable определяет, может ли значение свойства быть изменено по сравнению с его начальным значением. Мы можем сделать свойство name недоступным для записи, например,

'use strict'
var cat = { name: 'blacky', color: 'black'}
Object.defineProperty(cat, 'name', {writable: false})
console.log(Object.getOwnPropertyDescriptor(cat, 'name'))
cat.name = 'jacky'

Вывод:

{value: "blacky", writable: false, enumerable: true, configurable: true}
Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
    at <anonymous>:7:10

На приведенном выше мы видим, что мы получили ошибку. Потому что мы сделали свойство name недоступным для записи. Есть еще одна вещь, которую нужно посмотреть,

'use strict'
var cat = { name: {first: 'bla', last: 'cky'}, color: 'black'}
Object.defineProperty(cat, 'name', {writable: false})
console.log(Object.getOwnPropertyDescriptor(cat, 'name'))
cat.name.first = 'jacky'
console.log(cat.name)

Вывод:

{value: {…}, writable: false, enumerable: true, configurable: true}
{first: "jacky", last: "cky"}

В приведенном выше примере мы не видим никакой ошибки, хотя свойство name доступно только для чтения. имя — это просто указатель, указывающий на объект, содержащий первое и последнее свойство. и это предотвращает изменение этого указателя. Но на самом деле вы можете запретить изменение объекта с помощью object.freeze и давайте посмотрим, как это сделать.

'use strict'
var cat = { name: {first: 'bla', last: 'cky'}, color: 'black'}
Object.defineProperty(cat, 'name', {writable: false})
console.log(Object.getOwnPropertyDescriptor(cat, 'name'))
Object.freeze(cat.name)
cat.name.first = 'jacky'
console.log(cat.name)

Вывод:

{value: {…}, writable: false, enumerable: true, configurable: true}
Uncaught TypeError: Cannot assign to read only property 'first' of object '#<Object>'
    at <anonymous>:8:16

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

Теперь мы рассмотрим атрибут enumerable на примере,

'use strict'
var cat = { name: 'blacky', color: 'black'}
for(var key in cat) {
    console.log(key)
}

Вывод:

name
color

Мы можем перебирать свойства объекта cat. По умолчанию свойство объекта является перечисляемым. Мы можем это изменить,

'use strict'
var cat = { name: 'blacky', color: 'black'}
Object.defineProperty(cat, 'name', {enumerable: false})
for(var key in cat) {
    console.log(key)
}

Вывод:

color

В выводе мы видим только ключ свойства color. Изменение enumerable на false для name приводит к тому, что ключ не отображается в ключах объекта.

Атрибут configurable блокирует свойство, чтобы предотвратить изменение определенных атрибутов, а также предотвращает удаление свойства в объекте. Мы увидим на примере,

'use strict'
var cat = { name: 'blacky', color: 'black'}
Object.defineProperty(cat, 'name', {configurable: false})
Object.defineProperty(cat, 'name', {enumerable: false})

Вывод:

Uncaught TypeError: Cannot redefine property: name
    at Function.defineProperty (<anonymous>)
    at <anonymous>:6:8

У нас есть ошибка в этом случае. После установки для параметра configurable значения false мы не можем изменить определенные конфигурации свойства name. Теперь мы увидим, что он также предотвращает удаление свойства и выдает ошибку,

'use strict'
var cat = { name: 'blacky', color: 'black'}
Object.defineProperty(cat, 'name', {configurable: false})
delete cat.name

Вывод:

Uncaught TypeError: Cannot delete property 'name' of #<Object>
    at <anonymous>:6:1

Но теперь мы увидим, что мы меняем атрибут writable без каких-либо ошибок,

'use strict'
var cat = { name: 'blacky', color: 'black'}
Object.defineProperty(cat, 'name', {configurable: false})
Object.defineProperty(cat, 'name', {writable: false})

Здесь мы не получили никакой ошибки в выводе.

Вывод

Мы узнали об объекте Javascript и свойствах его свойств, а также о том, насколько они настраиваются.

Надеюсь, вам понравился этот блог...