W JavaSripcie istnieje bazowa klasa Object, która stanowi prototyp wszystkich pozostałych obiektów JavaScript. Można jej użyć bezpośrednio do utworzenia obiektu.
obj = new Object(); obj.x = 1; obj.y = 2; |
lub alternatywnie
obj = {}; obj.x = 1; obj.y = 2; |
Nawiasy klamrowe stanowią semantyczny skrót podobnie jak użycie nawiasów kwadratowych (arr = []) może zastąpić arr = new Array(). Tablica czyli Array jest jednym z wielu wbudowanych w JavaScript obiektów podobnie jak Window, Document itd.
Aby utworzyć niestandardowy obiekt należy najpierw zdefinować prototyp Klasy, której instancją dany obiekt będzie. Najprościej utworzyć prototyp metodą konstruktora.
var Foo = function() { this.x = 1; this.y = 2; this.sum = function() { return this.x + this.y; } } |
W konstruktorze definiujemy właściwości i metody. Nową instancję tworzy się z użyciem operatora new.
obj = new Foo(); alert(obj.x); alert(obj.sum()); |
Do właściwości lub metod można się odwołać za pośrednictwem utworzonego w ten sposób obiektu, ale można też pominąć operację przypisania do zmiennej i wywołać metodę w sposób niemożliwy np. w PHP.
alert(new Foo().sum()); |
Wywołując obj = new Foo(); powołuje się do życia instancje prototypu Foo. Można następnie wywołać metodę obj.sum();. Metodę sum można też wywołać z pominięciem przypisania obiektu do zmiennej new Foo().someMethod(); Tak czy inaczej zawsze w trzeba w pierwszej kolejności utworzyć obiekt.
Definiowanie klas metodą prototypu jest łatwe i intuicyjne, nie mniej w przypadku powoływania wielu obiektów danego prototypu zalecany jest sposób definiowania metod z użyciem prototype (nie mylić z frameworkiem prototype).
var Foo = function() { this.x = 1; this.y = 2; }; Foo.prototype.sum = function() { return this.x + this.y; } |
Różnica polega na tym, że w pierwszym przypadku przy powoływaniu do życia nowej instancji za każdym razem metoda „sum” tworzona jest na nowo, a w drugim przypadku jest to cały czas jedna i ta sama metoda. Zyskuję się na zaoszczędzonej pamięci co przy bardzo rozbudowanych skryptach nabiera znaczenia.
Zdefiniowanie metody z pominięciem słowa „prototype”:
var Foo = function() { }; Foo.sum = function(x, y) { return x+ y; } |
… daje możliwość wywołania metody klasy bez tworzenia obiektu Foo.sum(2,4); – to taki jakby odpowiednik metod statycznych w PHP. Analogicznie do metod statycznych w PHP użycie „this” wewnątrz takiej funkcji mija się z celem, więc gdybyśmy przez przypadek zdefiniowali:
var Foo = function() { this.x = 1; this.y = 2; }; Foo.sum = function() { return this.x + this.y; } |
to wywołanie Foo.sum(); zwróci „NaN” a z kolei new Foo().sum(); zakończy się błędem „TypeError on line 1: (new Foo).sum is not a function”.
W JS można też utworzyć obiekt ad hock
var Foo = { x: 1, y: 2, sum: function () { return this.x + this.y; } } |
W tym wypadku Foo nie jest prototypem tylko instancją prototypu Object dlatego oczywistym jest wywołanie Foo.sum(); z pominięciem operatora new.