W lekcji Tablice i obiekty opisałem ogólnie co to są obiekty i w jaki sposób można korzystać z tych które są udostępniane przez przeglądarkę internetową. Język JavaScript pozwala też na tworzenie własnych obiektów, i temu zagadnieniu poświęcona będzie ta część kursu.

Do stworzenia obiektu używa się funkcji – konstruktora. Jej jedyną cechą specjalną jest to że musi się nazywać tak samo jak tworzony obiekt. Do utworzenia instancji obiektu należy potem użyć tak jak zazwyczaj operatora new:

function Punkt()
{
}
 
var p = new Punkt();

Funkcja – konstruktor może też przyjmować parametry, przy pomocy których można np. zainicjować pola obiektu. Robi się to analogicznie jak tworząc nowe właściwości w już istniejących egzemplarzach obiektów – wystarczy przypisać wartość do właściwości którą chce się utworzyć. Ponieważ bieżący egzemplarz obiektu jest zawsze dostępny pod słowem kluczowym this, należy go użyc aby utworzyć właściwości:

function Punkt(x, y)
{
    this.x = x;
    this.y = y;
}
 
var p = new Punkt(10, 20);
alert("Współrzędne punktu to (" + p.x + "," + p.y + ")");

Poza właściwościami obiekt może też udostępniać metody (funkcje). Tworzy się je prosto – najpierw należy napisać funkcję, i następnie przypisać ją tak jak właściwości do obiektu. W funkcji takiej można odwołać się do bieżącej instancji obiektu za pomocą słowa kluczowego this. Przy tworzeniu takich funkcji polecam podać nazwę klasy jako prefiks nazwy (lub też inaczej je rozróżnić), tak aby od razu wiadomo było która funkcja należy do której klasy.

function Punkt_wypiszWspolrzedne()
{
    alert("Współrzędne punktu to (" + this.x + "," + this.y + ")");
}
 
function Punkt(x, y)
{
    this.x = x;
    this.y = y;
    this.wypiszWspolrzedne = Punkt_wypiszWspolrzedne;
}
 
var p = new Punkt(10, 20);
p.wypiszWspolrzedne();

Można też skorzystać z faktu że JavaScript pozwala na tworzenie funkcji anonimowych, które można od razu przypisać jako metody do obiektu:

function Punkt(x, y)
{
    this.x = x;
    this.y = y;
    this.wypiszWspolrzedne = function()
    {
        alert("Współrzędne punktu to (" + this.x + "," + this.y + ")");
    }
}
 
 
var p = new Punkt(10, 20);
p.wypiszWspolrzedne();

Przy tworzeniu własnych obiektów warto także utworzyć specjalną funkcję o nazwie toString(). Ta funkcja będzie wywoływana za każdym razem gdy zajdzie konieczność konwersji obiektu na string.

function Punkt_toString()
{
    return "(" + this.x + "," + this.y + ")";
}
 
function Punkt(x, y)
{
    this.x = x;
    this.y = y;
    this.toString = Punkt_toString;
}
 
var p = new Punkt(10, 20);
alert("Współrzędne punktu to " + p);

Po utworzeniu metody toString() można oczywiście wywołać ją także z innych metod klasy gdy zajdzie taka potrzeba. Można też wykorzystać fakt że język sam ją wywoła gdy będzie potrzeba, i po prostu skorzystać z możliwości tej niejawnej konwersji obiektu dostępnego poprzez słowo kluczowe this na string:

function Punkt_toString()
{
    return "(" + this.x + "," + this.y + ")";
}
 
function Punkt_wypiszWspolrzedne()
{
    alert("Współrzędne punktu to " + this);
}
 
function Punkt(x, y)
{
    this.x = x;
    this.y = y;
    this.toString = Punkt_toString;
    this.wypiszWspolrzedne = Punkt_wypiszWspolrzedne;
}
 
var p = new Punkt(10, 20);
p.wypiszWspolrzedne();

Każda klasa posiada także właściwość o nazwie prototype. Za jej pomocą można dodawać nowe właściwości i metody do już istniejących obiektów – zarówno tych utworzonych przez użytkownika, jak i tych wbudowanych w język:

String.prototype.KOMUNIKAT = "Komunikat: ";
String.prototype.podwoj = function() { return this + " " + this; }
 
var s = "Ala ma kota!";
alert(s.KOMUNIKAT + s.podwoj());

Istnieje też druga właściwość o nazwie constructor, która pozwala odwołać się do funkcji – konstruktora używanej to tworzenia obiektu. Można to np. użyć do sprawdzenia z obiektem jakiej klasy mamy do czynienia:

var x = "1" * 1;
if (x.constructor == String)
    alert("To jest string");
else
    alert("To nie jest string");

Ponieważ konstruktor jest również obiektem, więc posiada on też właściwość prototype. Można się do niej odwołać i dodać z jej użyciem kolejne właściwości i metody. W ten sposób można uzyskać znane z innych języków programowania składowe statyczne klasy (składowe które są przypisane do klasy, ale nie do obiektów które zostały utworzone na jej podstawie).

String.constructor.prototype.KOMUNIKAT = "Komunikat: ";
String.constructor.prototype.podwoj = function(s) { return s + " " + s; }
 
alert(String.KOMUNIKAT + String.podwoj("Ala ma kota!"));