Obiekty można tworzyć używając new Object()
, Object.create()
, bądź wykorzystując notację literałową (notację inicializacyjną). Inicjalizator obiektu to lista zera lub więcej par - nazw właściwości oraz ich wartości - otoczonych nawiasami klamrowymi ({}
).
Składnia
var o = {};
var o = { a: "foo", b: 42, c: {} };
var a = "foo", b = 42, c = {};
var o = { a: a, b: b, c: c };
var o =
{
wlasciwosc: function ([parametry]) {},
get wlasciwosc() {},
set wlasciwosc(wartosc) {},
};
Nowe notacje w ECMAScript 2015
Pamiętaj aby zapoznać się z tabelą kompatybilności. Środowiska nie obsługujące tych notacji będą wyrzucać błędy składni.
// Skrótowe nazwy właściwości (ES6)
var a = "foo", b = 42, c = {};
var o = { a, b, c };
// Skrótowe nazwy metod (ES6)
var o = {
wlasciwosc([parametry]) {},
get wlasciwosc() {},
set wlasciwosc(wartosc) {},
* generator() {}
};
// Obliczone nazwy właściwości (ES6)
var nazwa = "foo";
var o = {
[nazwa]: "dzien",
["b" + "ar"]: "dobry",
};
Opis
Inicjalizator obiektu to wyrażenie opisujące inicjalizację obiektu Object
. Obiekty składają się z właściwości używanych do opisywania obiektu. Wartości tych właściwości mogą zawierać primitive typy danych albo inne obiekty.
Tworzenie obiektów
Pusty obiekt możemy stworzyć w taki sposób:
var obiekt = {};
Jednak prawdziwą przewagą notacji literałowej jest możliwość tworzenia w szybki sposób obiektów ze zdefiniowanymi od razu właściwościami. Wystarczy wypisać listę kluczy: wartości odzdzielonych dwukropkiem. Poniższy przykład tworzy obiekt osoba
z trzema właściwościami: "imie
", "wiek
" i "wyglad
". Ich wartościami jest string "Adam
", numer 42
oraz inny obiekt.
var osoba =
{
imie: "Adam",
wiek: 42,
wyglad: { wzrost: 179 },
}
Dostęp do właściwości
Kiedy już stworzyłeś obiekt, możesz chcieć zobaczyć lub zmienić jego właściwości. Można zrobić to używając zapisu z kropką lub nawiasami. Zajrzyj do operatorów pamięci po więcej informacji.
object.imie; // "Adam"
object["wiek"]; // 42
object.imie = "Ewa";
Definiowanie właściwości
Nauczyliśmy się już jak zapisywać właściwości używając notacji literałowej. Czasami jednak mamy w kodzie zmienne, które chcielibyśmy dodać do naszego obiektu. Możemy to zrobić w taki sposób:
var a = "foo",
b = 42,
c = {};
var o =
{
a: a,
b: b,
c: c
};
Ale ECMAScript 2015 oddaje nam do dyspozycji krótszy zapis, pozwalający uzyskać ten sam efekt:
var a = "foo",
b = 42,
c = {};
// Skrótowe nazwy właściwości (ES6)
var o = { a, b, c };
Duplikowanie nazw właściwości
W momencie, gdy użyjemy już istniejącej nazwy właściwości jej wartość nadpisze tę poprzednią.
var a = {x: 1, x: 2};
console.log(a); // { x: 2}
W ECMAScript 5 strict mode, duplikowanie nazw właściwości było postrzegane jako SyntaxError
. Zmieniono to jednak po wprowadzeniu obliczanych nazw właściwości. Duplikacja stała się wówczas możliwa podczas wykonywania kodu, dlatego też w ECMAScript 2015 usunięto tę rystrykcję.
function czyES6UmozliwiaDuplikowanieWlasciwosci()
{
"use strict";
try
{
({ prop: 1, prop: 2 });
// Nie wyrzucono błędu, duplikacja dozwolona w strict mode.
return true;
}
catch (e)
{
// Wyrzucono błąd, duplikacja w strict mode zabroniona.
return false;
}
}
Definicje metod
Właściwość obiektu może również odnosić się do funkcji albo metody getter lub setter.
var o = {
wlasciwos: function ([parametry]) {},
get wlasciwos() {},
set wlasciwos(wartosc) {},
};
w ECMAScript 2015, mamy dostęp do skróconego zapisu, takiego w którym słowo kluczowe "function" nie jest nam już potrzebne.
// Shorthand method names (ES6)
var o = {
property([parameters]) {},
get property() {},
set property(value) {},
* generator() {}
};
W ECMAScript 2015 możemy również w prostszy sposób zapisać właściwość będącą funkcją generatora:
var o = {
* generator() {
...........
}
};
W ECMAScript 5 musielibyśmy zapisać to tak (aczkolwiek pamiętaj że w ES5 nie ma generatorów):
var o = {
generator: function *() {
...........
}
};
Po więcej informacji zajrzyj do definicji metod.
Obliczone nazwy właściwości
Od ECMAScript 2015, składnia inicjalizatora obiektu wspiera także obliczone nazwy właściwości. Umożliwia to umieszczenie wyrażenia w nawiasach []
, które potem zostanie przeliczone na nazwę właściwości. Działa to na tej samej zasadzie co zapis klamrowy w operatorach pamięci, z którymi zapewne miałeś już styczność. Teraz możemy użwać tej samej składni w notacji literałowej:
// Obliczone nazwy właściwości (ES6)
var i = 0;
var 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
var param = 'typ';
var info = {
[param]: 'strona',
["pod" + param.charAt(0).toUpperCase() + param.slice(1)]: 'forum'
};
console.log(info); // { typ: 'strona', 'podTyp': 'forum' }
Zmiana prototypu
Definicja właściwości w formie __proto__: wartosc
albo "__proto__": wartosc
nie stworzy właściwości z nazwą __proto__
. Zamiast tego, jeżeli podana wartość jest obiektem lub typem null
, zamieni ona [[Prototype]]
tworzonego obiektu na podaną wartość. (Jeżeli wartość nie jest ani obiektem ani typem null
prototyp nie zostanie zmieniony.)
var obj1 = {};
console.log(Object.getPrototypeOf(obj1) === Object.prototype); // true
var obj2 = { __proto__: null };
console.log(Object.getPrototypeOf(obj2) === null); // true
var protoObj = {};
var obj3 = { "__proto__": protoObj };
console.log(Object.getPrototypeOf(obj3) === protoObj); // true
var obj4 = { __proto__: "not an object or null" };
console.log(Object.getPrototypeOf(obj4) === Object.prototype); // true
console.log(!obj4.hasOwnProperty("__proto__")); // true
Podczas notacji literałowej możemy zmienić prototyp tylko raz, kolejne próby będą skutkować błędami składni.
Jeżeli użyjemy w defninicji nazwy __proto__
bez używania składni z dwukropkiem, nazwa ta będzie się zachowywać jak kazda inna.
var __proto__ = "wartosc";
var obj1 = { __proto__ };
console.log(Object.getPrototypeOf(obj1) === Object.prototype); // true
console.log(obj1.hasOwnProperty("__proto__")); // true
console.log(obj1.__proto__ === "wartosc"); // true
var obj2 = { __proto__() { return "witaj"; } };
console.log(obj2.__proto__() === "witaj"); // true
var obj3 = { ["__prot" + "o__"]: 17 };
console.log(obj3.__proto__ === 17); // true
Notacja literałowa vs JSON
Notacja literałowa to nie to samo co JavaScript Object Notation (JSON). Pomimo, że wyglądają podobnie, są miedzy nimi poważne różnice:
- JSON dopuszcza tylko składnie
"wlasnosc": wartosc
. Nazwa własności musi być w cudzysłowie, a defnicja nie może być skrócona. - W JSON wartościami moga być tylko string'i, liczby, tablice,
true
,false
,null
, lub inny obiekt JSON. - Funkcja nie może być przypisana do wartości w JSON.
- Obiekty jak
Date
zostaną zamienione na string po użyciuJSON.parse()
. JSON.parse()
odrzuni obliczone nazwy zmiennych oraz wyrzuci błąd.
Specyfikacje
Specification | Status | Comment |
---|---|---|
ECMAScript 1st Edition (ECMA-262) | Standard | Początkowa definicja. |
ECMAScript 5.1 (ECMA-262) The definition of 'Object Initializer' in that specification. |
Standard | Dodano metody getter oraz setter. |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Object Initializer' in that specification. |
Standard | Skrócone nazwy właściwości/metod oraz obliczone nazwy właściwości. |
ECMAScript (ECMA-262) The definition of 'Object Initializer' in that specification. |
Living Standard |
Kompatybilność z przeglądarkami
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | 1.0 | 1.0 (1.7 or earlier) | 1 | 1 | 1 |
Computed property names | (Yes) | 34 (34) | No support | No support | 7.1 |
Shorthand property names | (Yes) | 33 (33) | No support | No support | No support |
Shorthand method names | 42.0 | 34 (34) | No support | No support | No support |
Feature | Android | Android Webview | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile | Chrome for Android |
---|---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | 1.0 (1.0) | 1 | 1 | 1 | 1.0 |
Computed property names | No support | (Yes) | 34.0 (34) | No support | No support | No support | No support |
Shorthand property names | No support | (Yes) | 33.0 (33) | No support | No support | No support | No support |
Shorthand method names | No support | 42.0 | 34.0 (34) | No support | No support | No support | 42.0 |