Атрибуты свойств и метод Object.create()

Создать объект можно с помощью статического метода create() из класса Object:

<Объект> = Object.create(<Прототип>[, <Опции>])

Если в первом параметре указать значение null, то будет создан объект без наследования свойств класса Object:

let obj = Object.create(null);
obj.a = 1;
console.log( obj.a );          // 1
console.log( obj.toString );   // undefined

Чтобы получить обычный объект, в первом параметре нужно указать значение Object.prototype:

let obj = Object.create(Object.prototype);
obj.a = 1;
console.log( obj.a );          // 1
console.log( obj.toString );   // [Function: toString]

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

let objA = Object.create(Object.prototype);
objA.a = 10;
let objB = Object.create(objA);
objB.b = 55;
console.log(objB.a);                        // 10
console.log(objB.b);                        // 55

Если в первом параметре указать значение отличное от объекта и null, то будет сгенерировано исключение:

let obj = Object.create(undefined);
// TypeError: Object prototype may only be an 
// Object or null: undefined

Второй параметр позволяет сразу добавить свойства в созданный объект. В качестве значения указывается объект:

{
   <Свойство 1>: <Объект с настройками>[,
   ...,
   <Свойство N>: <Объект с настройками>]
}

Пример:

let objA = Object.create(Object.prototype, {
   'a': { value: 10 }
});
let objB = Object.create(objA, {
   'b': { value: 55 },
   'c': { value: 4 }
});
console.log(objB.a);  // 10
console.log(objB.b);  // 55
console.log(objB.c);  // 4

И тут начинается самое интересное. Если мы сейчас попробуем вывести объекты в консоль, то получим пустые объекты, т. к. свойства не являются перечислимыми:

console.log(objA);    // {}
console.log(objB);    // {}
console.log( objA.propertyIsEnumerable('a') ); // false
console.log( objB.propertyIsEnumerable('b') ); // false
console.log( objB.propertyIsEnumerable('c') ); // false

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

objB.c = 17;
console.log(objB.c);  // 4, а не 17 !

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

console.log(delete objB.c); // false
console.log(objB.c);        // 4

В обычном режиме никаких ошибок не выводится. Однако при использовании строгого режима (добавьте инструкцию 'use strict'; в начало файла) последние два примера приведут к исключениям:

TypeError: Cannot assign to read only property 'c' of object '#<Object>'
TypeError: Cannot delete property 'c' of #<Object>

Итак, по умолчанию при создании объекта с помощью метода create() все атрибуты свойств имеют значение false, тогда как при создании объекта с помощью фигурных скобок все атрибуты имеют значение true. Для управления атрибутами нужно указать следующие опции в параметре <Объект с настройками>:

  • value — задает значение свойству. Значение по умолчанию: undefined. Опцию нельзя указывать одновременно с опциями set и get;
  • writable — если опция имеет значение true, то делает свойство записываемым (значение свойства можно изменять, в противном случае свойство доступно только для чтения). Значение по умолчанию: false. Опцию нельзя указывать одновременно с опциями set и get;
  • configurable — если опция имеет значение true, то делает свойство настраиваемым (свойство можно будет удалить с помощью оператора delete и менять в дальнейшем). Значение по умолчанию: false;
  • enumerable — если опция имеет значение true, то делает свойство перечислимым (свойство можно перебирать с помощью цикла for...in). Значение по умолчанию: false;
  • set — задает функцию (setter) для изменения значения. Значение по умолчанию: undefined;
  • get — задает функцию (getter) для получения значения. Значение по умолчанию: undefined.

Пример указания опций во втором параметре метода create():

let objA = Object.create(Object.prototype, {
   'a': {
      value: 10,
      writable: true,
      configurable: true,
      enumerable: true
   }
});
let objB = Object.create(objA, {
   'b': { value: 55, enumerable: true },
   'c': {
      enumerable: true,
      set: function(value) {
         this._c = value;
      },
      get: function() {
         return this._c;
      }
   },
   '_c': { writable: true }
});
console.log(objB.a);  // 10
console.log(objB.b);  // 55
console.log(objB._c); // undefined
objB.c = 4;
console.log(objB.c);  // 4
console.log(objB._c); // 4
console.log(objA);    // { a: 10 }
console.log(objB);    // { b: 55, c: [Getter/Setter] }

Учебник по Node.js и JavaScript
Учебник по JavaScript (Node.js) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов