Ініціалізатор об’єкта

Об'єкти можна ініціалізувати через new Object()Object.create(), або за допомогою літеральної нотації (нотації ініціалізатора). Ініціалізатор об'єкта - це список з нуля або більше розділених комою пар імен властивостей та асоційованих з ними значень об'єкта, записаних у фігурних дужках ({}).

Синтаксис

let o = {}
let o = {a: 'няв', b: 42, c: {}}

let a = 'няв', b = 42, c = {}
let o = {a: a, b: b, c: c}

let o = {
  property: function ([parameters]) {},
  get property() {},
  set property(value) {}
};

Нові позначення у ECMAScript 2015

Будь ласка, перевірте підтримку цих позначень у таблиці сумісностей. У тих середовищах, де вони не підтримуються, вони призведуть до синтаксичних помилок.

// Скорочений запис імен властивостей (ES2015)
let a = 'привіт', b = 42, c = {};
let o = {a, b, c}

// Скорочений запис імен методів (ES2015)
let o = {
  property([parameters]) {}
}

// Обчислювані імена властивостей (ES2015)
let prop = 'foo'
let o = {
  [prop]: 'як',
  ['b' + 'ar']: 'справи'
}

Опис

Ініціалізатор об'єкта - це вираз, який описує ініціалізацію об'єкта. Об'єкт складається з властивостей, які описують цей об'єкт. Значення властивостей об'єкта можуть містити або прості типи даних, або інші об'єкти.

Літеральна нотація об'єкта та JSON

Літеральна нотація об'єкта - це не те саме, що запис об'єктів JavaScript (JavaScript Object Notation, JSON). Хоча вони схожі, між ними є кілька відмінностей:

  • JSON дозволяє визначення властивості тільки у форматі "property": value. Ім'я властивості має бути записане у подвійних лапках, а визначення не може бути скороченим.
  • У JSON значення можуть бути тільки рядками, числами, масивами, true, false, null або іншими об'єктами (JSON).
  • Функція (дивіться "Визначення методів") не може бути присвоєна як значення у JSON.
  • Об'єкти типу Date перетворяться на рядок після виклику JSON.parse().
  • JSON.parse() відхилить обчислювані імена властивостей, буде викинута помилка.

Приклади

Створення об'єктів

Порожній об'єкт без властивостей може бути створений так:

let object = {}

Однак, перевагою літералу або ініціалізатора об'єкта є те, що ви можете швидко створити об'єкт з властивостями всередині фігурних дужок. Ви просто позначаєте список пар key: value, розділених комами.

Наступний код створює об'єкт з трьома властивостями, його ключами є "foo", "age" та "baz". Значеннями цих ключів є рядок "bar", число 42, а третя властивість має інший об'єкт в якості свого значення.

let object = {
  foo: 'bar',
  age: 42,
  baz: {myProp: 12}
}

Доступ до властивостей

Коли ви створили об'єкт, ви можете захотіти прочитати чи змінити його. До властивостей об'єкта можна звертатись, використовуючи крапкову нотацію або дужкову нотацію. Читайте Доступ до властивостей, щоб дізнатись більше.

object.foo // "bar"
object['age'] // 42

object.foo = 'baz'

Визначення властивостей

Ми вже дізнались, як позначати властивості за допомогою синтаксису ініціалізатора. Часто у коді є змінні, які ви б хотіли використати в об'єкті. Ви побачите код на зразок такого:

let a = 'foo', 
    b = 42,
    c = {};

let o = { 
  a: a,
  b: b,
  c: c
}

У ECMAScript 2015 є коротше позначення, яке робить те саме:

let a = 'foo', 
    b = 42, 
    c = {};

// Скорочений запис імен властивостей (ES2015)
let o = {a, b, c}

// Іншими словами,
console.log((o.a === {a}.a)) // true

Дублювання імен властивостей

Якщо використовуються однакові імена властивостей, друга властивість перепише першу.

var a = {x: 1, x: 2};
console.log(a); // {x: 2}

У строгому режимі ECMAScript 5 дублювання імен властивостей вважалося помилкою SyntaxError. З появою обчислюваних імен властивостей, що робило дублювання можливим під час виконання, це обмеження було прибране з ECMAScript 2015.

function haveES2015DuplicatePropertySemantics() {
  'use strict';
  try {
    ({prop: 1, prop: 2});

    // Помилка не викидається, дублікати дозволені у строгому режимі
    return true;
  } catch(e) {
    // Помилка викидається, дублікати заборонені у строгому режимі
    return false;
  }
}

Визначення методів

Властивість об'єкта може також посилатись на функцію або гетер чи сетер.

let o = {
  property: function ([parameters]) {},
  get property() {},
  set property(value) {}
}

У ECMAScript 2015 доступне скорочене позначення, тому ключове слово "function" більше не є обов'язковим.

// Скорочений запис імен методів (ES2015)
let o = {
  property([parameters]) {},
}

У ECMAScript 2015 є можливість стисло визначати властивості, значеннями яких є функції-генератори:

let o = {
  *generator() {
    ...........
  }
};

Що є еквівалентним цьому позначенню в стилі ES5 (але зауважте, що у ECMAScript 5 немає генераторів):

let o = {
  generator: function* () {
    ...........
  }
}

Більше інформації та прикладів щодо методів дивіться у статті визначення методів.

Обчислювані імена властивостей

Починаючи з ECMAScript 2015, синтаксис об'єктного ініціалізатора також підтримує обчислювані імена властивостей. Це дозволяє розташувати вираз у квадратних дужках [], і він буде обчислений як ім'я властивості. Цей синтаксис є аналогічним дужковій нотації у доступі до властивостей, який ви вже могли використовувати, щоб читати та встановлювати властивості. Тепер ви можете використовувати такий самий синтаксис і для об'єктних літералів:

// Обчислювані імена властивостей (ES2015)
let i = 0
let a = {
  ['foo' + ++i]: i,
  ['foo' + ++i]: i,
  ['foo' + ++i]: i
}

console.log(a.foo1) // 1
console.log(a.foo2) // 2
console.log(a.foo3) // 3

let param = 'size'
let config = {
  [param]: 12,
  ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4
}

console.log(config) // {size: 12, mobileSize: 4}

Розкладені властивості

Пропозиція Rest/Spread Properties for ECMAScript (стадія 4) додає розкладені властивості до об'єктних літералів. Ця функціональність копіює особисті перелічувані властивості з наданого об'єкта у новий об'єкт.

Дрібне клонування (не включає prototype) чи злиття об'єктів тепер можливе з використанням синтаксису, коротшого, ніж Object.assign().

let obj1 = { foo: 'bar', x: 42 }
let obj2 = { foo: 'baz', y: 13 }

let clonedObj = { ...obj1 }
// Object { foo: "bar", x: 42 }

let mergedObj = { ...obj1, ...obj2 }
// Object { foo: "baz", x: 42, y: 13 }

Зауважте, що Object.assign() запускає сетери, а оператор розкладу ні!

Мутація прототипу

Визначення властивості виду __proto__: value чи "__proto__": value не створює властивість з іменем __proto__. Замість цього, якщо надане значення є об'єктом чи null, воно змінює [[Prototype]] створеного об'єкта на це значення. (Якщо значення не є об'єктом чи null, об'єкт не змінюється.)

let obj1 = {};
assert(Object.getPrototypeOf(obj1) === Object.prototype);

let obj2 = {__proto__: null};
assert(Object.getPrototypeOf(obj2) === null);

let protoObj = {};
let obj3 = {'__proto__': protoObj};
assert(Object.getPrototypeOf(obj3) === protoObj);

let obj4 = {__proto__: 'не об\'єкт чи null'};
assert(Object.getPrototypeOf(obj4) === Object.prototype);
assert(!obj4.hasOwnProperty('__proto__'));

У об'єктному літералі дозволена лише одна мутація: декілька мутацій прототипу є синтаксичною помилкою.

Визначення властивостей, які не використовують нотацію з двокрапкою, не є мутаціями прототипу: вони є визначеннями властивостей, які поводяться ідентично до схожих визначень, що використовують будь-яке інше ім'я.

let __proto__ = 'змінна';

let obj1 = {__proto__};
assert(Object.getPrototypeOf(obj1) === Object.prototype);
assert(obj1.hasOwnProperty('__proto__'));
assert(obj1.__proto__ === 'змінна');

let obj2 = {__proto__() { return 'привіт'; }};
assert(obj2.__proto__() === 'привіт');

let obj3 = {['__prot' + 'o__']: 17};
assert(obj3.__proto__ === 17);

Специфікації

Специфікація
ECMAScript (ECMA-262)
The definition of 'Object Initializer' in that specification.

Сумісність з веб-переглядачами

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Object initializerChrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 1Opera Full support 4Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Computed property namesChrome Full support 47Edge Full support 12Firefox Full support 34IE No support NoOpera Full support 34Safari Full support 8WebView Android Full support 47Chrome Android Full support 47Firefox Android Full support 34Opera Android Full support 34Safari iOS Full support 8Samsung Internet Android Full support 5.0nodejs Full support 4.0.0
Shorthand method namesChrome Full support 47Edge Full support 12Firefox Full support 34IE No support NoOpera Full support 34Safari Full support 9WebView Android Full support 47Chrome Android Full support 47Firefox Android Full support 34Opera Android Full support 34Safari iOS Full support 9Samsung Internet Android Full support 5.0nodejs Full support 4.0.0
Shorthand property namesChrome Full support 47Edge Full support 12Firefox Full support 33IE No support NoOpera Full support 34Safari Full support 9WebView Android Full support 47Chrome Android Full support 47Firefox Android Full support 33Opera Android Full support 34Safari iOS Full support 9Samsung Internet Android Full support 5.0nodejs Full support 4.0.0
Spread properties
Experimental
Chrome Full support 60Edge Full support 79Firefox Full support 55IE No support NoOpera Full support 47Safari Full support 11.1WebView Android Full support 60Chrome Android Full support 60Firefox Android Full support 55Opera Android Full support 44Safari iOS Full support 11.3Samsung Internet Android Full support 8.0nodejs Full support 8.3.0

Legend

Full support  
Full support
No support  
No support
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.

Див. також