Objektově orientované programování v JavaScriptu

JavaScript Objektově orientované programování Objektově orientované programování v JavaScriptu

Když funkce přestanou stačit, začínáme se ve skriptech ztrácet a kód není nic jiného než změť nijak neuspořádaných globálních funkcí a proměnných, které se hojně přepisují a manipuluje se s nimi, přestává nám procedurální programování stačit a nastupuje objektové programování (ve zkratce OOP - objektově orientované programování). Některé moderní programovací jazyky ani možnost procedurálního programování nenabízejí, jiné zase nabízejí jen to procedurální nebo dokonce obojí. V JavaScriptu si můžete vybrat.

Reference

Vlastností JavaScriptu je tzv. systém referencí. Reference ukazuje na aktuální umístění objektu, což je velmi užitečná vlastnost. Předpokládá, že objekt není nikdy referencí. Text řetězec je vždy textovým řetězcem a číslo je vždy číslem, ale několik proměnných může ukazovat na stejný objekt. Na tomto systému je založen JavaScript.

V kostce tento systém referencí říká, že když máme objekt uložen ve více proměnných, úpravou objektu v jedné proměnné upravíme objekty ve všech těch proměnných. Je to způsobeno právě tím, že proměnné na daný objekt jen ukazují, a nejedná se tedy o kopii objektu.

var zprava = ["Hello", "World"];
var dalsiPole = zprava;
dalsiPole.push("!");
alert( zprava.join(" ") );

Tento skript vypíše "Hello World !" i když jsme další položku ("!") přidali do pole dalsiPole, toto pole jen ukazovalo na objekt zprava. Tím pádem pokud změníme objekt v jedné z těchto proměnných, změní se všude. Pokud ovšem vytvoříme nový objekt pole, do kterého uložíme proměnné, úprava se projeví jen v jednom z nich.

Kontext

V JavaScriptu pracujeme vždy v nějakém kontextu. Kontext je v podstatě objekt uvnitř kterého pracujeme. Nachází se i v jiných objektově orientovaných jazycích, ale ne v takové míře jako v JavaScriptu.

Kontext reprezentuje klíčové slovo this. To obsahuje vždy objekt, ve kterém se právě nacházíme. I když definujeme globální proměnné a funkce, stále se jedná o funkce a proměnné uložené do objektu window, a tak i tady bude kontext a to právě window. V JavaScriptu má každý objekt svůj vlastní kontext, který lze měnit. Změnit kontext lze pomocí funkce apply. Apply je metoda objektu Function. Má dva argumenty, kontext a pole parametrů, se kterými chceme zavolat funkci.

Vytváření objektů

Objekty jsou základní prvky jazyka JavaScript. Prakticky na každý prvek v JavaScriptu lze pohlížet jako na objekt. Můžeme si je sami vytvářet. Způsobů, jak vytvořit objekt je několik. Jedním z nich je použití new Object(), který vytvoří prázdný objekt. Proměnné a metody do něj pak můžeme přidávat tzv. inline zápisem.

var clanek = new Object();
clanek.titulek = "OOP v JS";
clanek.text = "JavaScript a OOP";
clanek.publikovan = false;

clanek.publikovat = function() {
        this.publikovan = true;
}

Tento kód vytvoří objekt clanek, který bude mít titulek "OOP v JS", text "JavaScript a OOP". Obsahuje také metodu, která publikuje daný článek.

Další způsob, jak vytvářet objekty v JavaScriptu je přímo nadefinovat vlastnosti a funkce do složených závorek. Zápis objektu článku by tedy mohl vypadat takto:

var clanek = {
        titulek: "OOP v JS",
        text: "JavaScript a OOP",
        publikovan: false,

        publikovat: function() {
                this.publikovan = true;
        }
};

alert( "Titulek: " + clanek.titulek +  " Text: " + clanek.text + " Publikován: " + clanek.publikovan  );
clanek.publikovat();
alert( "Titulek: " + clanek.titulek +  " Text: " + clanek.text + " Publikován: " + clanek.publikovan  );

Zde jste si určitě všimli i způsobu, jak se jednotlivé vlastnosti nebo funkce volají. Klíčové slovo this v metodě publikovat zastupuje objekt, ve kterém se nachází daná funkce. To se nazývá kontext funkce.

Objekt jako pole

V JavaScriptu lze k veškerým objektům přistupovat jako k asociativnímu poli. Můžeme tak vlastnosti a metody objektu procházet cyklem for nebo k nim přímo přistupovat tak, že jako index položky v poli použijeme název vlastnosti či metody. Objekt článku bychom tak mohli projít například:

for(var i in clanek) {
        alert(clanek[i]);
}

Konstruktor a prototypy

Způsoby definice objektů, které jsme si ukázali jsou sice dobré, ale celkem nás omezují. Co když budeme chtít publikovat více článků? Museli bychom vytvořit pro každý článek speciální nový objekt, což je nepraktické. V JavaScriptu to samozřejmě můžeme udělat lépe. Lze použít takzvaný konstruktor objektu, od kterého pak můžeme vytvořit nové objekty (instance) pro každý článek, proto se mu také říká třída. Konstruktor je v JavaScriptu vyjádřen funkcí. Každá funkce může být konstruktorem objektu. Pokud zavoláme funkci s klíčovým slovem new, vytvoříme tak novou instanci (objekt). V konstruktoru můžeme opět použít klíčové slovo this pro přístup k funkcím či metodám daného objektu.

var Clanek = function( titulek, text ) {
        this.titulek = titulek;
        this.text = text;
        this.publikovan = false;

        this.publikovat = function() {
                this.publikovan = true;
        }
}

var oop = new Clanek("OOP v JS", "JavaScript a OOP");
var algoritmy = new Clanek("Algoritmy", "Lorem ipsum, dolor sit amet ...");

alert( "Titulek: " + oop.titulek +  " Text: " + oop.text + " Publikován: " + oop.publikovan  );
alert( "Titulek: " + algoritmy.titulek +  " Text: " + algoritmy.text + " Publikován: " + algoritmy.publikovan  );

Máme konstruktor objektu článku a můžeme od něj vytvořit článek s libovolným titlkem a textem. Konstruktor, jak sami vidíte, může stejně jako funkce obsahovat parametry, které mu pak musíme předat při vytváření objektu (new Clanek(prvníPa­rametr, druhyParametr)).

Každý konstruktor má svůj prototyp, který je uložen v proměnné objektu zvané prototype. Jedná se opět o objekt, který reprezentuje instanci. Zní to celkem složitě, ale v podstatě je to velmi jednoduché. V prototypu jsou uloženy všechny funkce a vlastnosti. Po vytvoření nové instance objektu se tyto vlastnosti a funkce vloží do objektu. V JavaScriptu se prototypy využívají k tzv. dědičnosti.

var Clanek = function( titulek, text ) {
    this.titulek = titulek;
    this.text = text;
}

Clanek.prototype.publikovan = false;
Clanek.prototype.publikovat = function() {
    this.publikovan = true;
}

var oop = new Clanek("OOP v JS", "JavaScript a OOP");

alert( "Titulek: " + oop.titulek +  " Text: " + oop.text + " Publikován: " + oop.publikovan  );

Tento zápis vlastností a funkcí objektu je stejný, jako ten před tím. Rozdíl je v tom, že jsou metody uložené v prototypu. Oddělili jsme tak konstruktor objektu od vlastností a funkcí. Všechny metody se navíc inicializují pouze jednou, což neplatí u předchozího příkladu, kde jsme je přidávali přímo ve funkci. Možná jste si všimli způsobu zápisu funkcí a vlastností do prototypu. Použil jsem inline zápis do objektu. Lze samozřejmě použít i přímý způsob zápisu (ve složených závorkách). Do prototypu jednotlivých objektů můžeme připisovat další metody a proměnné. Tak lze rozšiřovat již existující objekty o nové funkce.

String.prototype.addSlashes = function() {
    return this.replace(/[\\"']/g, '\\$&');
}

var test = "Textový řetězec: 'hello world'".addSlashes ();
alert( test );

Tento příklad přidá zpětné lomítko za každou uvozovku v daném textu. Pokud jsi ještě vzpomenete na začátek článku, tak jsem říkal, že vše v JavaScriptu je objekt včetně čísel (Number), textového řetězce (String), logických hodnot true/false (Boolean), pole (Array), datum (Date), regulerní výraz (RegExp), objekt (Object) a dokonce i funkce (Function). To vše jsou konstruktory (třídy) objektů, do kterých můžeme přidávat další funkce. Zároveň se automaticky vytvářejí (tzn. proměnná s číslem je automaticky instance objektu Number a lze na ni aplikovat všechny vestavěné metody včetně těch námi vytvořených). Tímto způsobem se dá rozšířit jakýkoli objekt v JavaScriptu.

Operátory instanceof a typeof

V objektově orientovaném programování se určitě setkáte s těmito dvěma operátory. Operátor instanceof testuje, zda má daný objekt v prototypu prototyp konstruktoru (zda byl objekt vytvořen od dané třídy). Vrací logickou hodnotu true/false (Boolean).

Syntaxe
objekt instanceof třída
Příklad
if ( oop instanceof Clanek )
        alert("V proměnné 'oop' je uložen článek");

if ( !(oop instanceof Clanek) )
        alert("V proměnné 'oop' není uložen článek");
typeof

Operátor typeof vrací textový řetězec identifikující typ prvku.

Syntaxe
typeof prvek
typeof(prvek)
Příklad
if ( typeof oop == "object" )
        alert("V proměnné 'oop' je uložen objekt");

if ( !(typeof oop == "object") )
        alert("V proměnné 'oop' není uložen objekt");
Tabulka návratových hodnot
Typ Vrací
undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Function "function"
XML objekt "xml"
Další objekty "object"

Tak a to je pro dnešek vše. Příště se v podíváme na návrhové vzory v JavaScriptu a ukážeme si nějakou reálnou aplikaci v OOP.


 

  Aktivity (1)

Článek pro vás napsal Drahomír Hanák
Avatar
Autor v současné době studuje Informatiku. Zajímá se o programování, matematiku a grafiku.

Jak se ti líbí článek?
Celkem (12 hlasů) :
55555


 



 

 

Komentáře
Zobrazit starší komentáře (2)

Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:

Super článek, teď se mi to hodí :)

Odpovědět  +2 25.3.2013 19:07
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Drahomír Hanák
Tým ITnetwork
Avatar
Odpovídá na David Čápka
Drahomír Hanák:

Tak jsem rád, že se článek líbí :) Třeba někdy budu mít čas dopsat nějaké pokračování, kdyby byl zájem, ale už mám ve frontě dost jiných článků.

 
Odpovědět  +2 25.3.2013 19:51
Avatar
Pavel Vosyka
Člen
Avatar
Pavel Vosyka:

Parádní článek, díky za něj! Víc takových :). Dělám teď jeden svůj projektík a celý v javascriptu (takový SPA pokus) no ale přesně jak píšeš - hromada funkcí a proměnných, logika a výstup se mi mýchaj dohromady. Těším se na další pokračování.

Odpovědět  +1 25.8.2013 17:44
"nikdy nepiš nic 2x"
Avatar
Pavel Vosyka
Člen
Avatar
Pavel Vosyka:

//omyl

Editováno 25.8.2013 17:52
Odpovědět 25.8.2013 17:52
"nikdy nepiš nic 2x"
Avatar
Odpovídá na Pavel Vosyka
Michal Žůrek (misaz):

já myslím že javascript toho oop moc nenabízí...

Odpovědět 25.8.2013 17:53
Nesnáším {}, proto se jim vyhýbám.
Avatar
Kit
Redaktor
Avatar
Odpovědět  +3 25.8.2013 17:56
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Zdeněk Pavlátka:

Jde vytvořit pole objektů, které mají konstruktor s více parametry bez použití cyklu for?

Odpovědět 24.9.2013 20:30
Kolik jazyků umíš, tolikrát jsi programátor.
Avatar
Odpovídá na Zdeněk Pavlátka
Michal Žůrek (misaz):
var pole = [new Objekt(1,2,3), new Objekt(1, 3, 2), new Objekt(3, 2, 1), ...]
Odpovědět 24.9.2013 20:32
Nesnáším {}, proto se jim vyhýbám.
Avatar
patrik.valkovic
Šéfredaktor
Avatar
patrik.valkovic:

Skvělý článek, velmi bych uvítal pokračování. Na dědičnost a tak :)
OOP v JS, to je na zlost fakt :D

Odpovědět  +1 25.12.2013 11:42
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Nezmar Hydra
Člen
Avatar
Nezmar Hydra:

Proč mi objekt nefunguje ve standartním módu ( <!doctype html> )
zatíco v quirk módu ( <!DOCTYPE HTML PUBLIC "-W3CDTD HTML 4.0 Transitional//EN"> ,nebo bez zápisu)
bez problému funguje?

var obj={
T:1, // - Timer
smenu:"",
HT:"",
HeightOfMenu:460,

reads:function()
{
this.smenu=do­cument.getEle­mentById("side­bar");
this.HT=documen­t.body.clientHe­ight-this.HeightOfMenu;
this.smenu.sty­le.top=documen­t.getElementsBy­TagName("body")­.item(0).scro­llTop+obj.HT;
setTimeout("ob­j.reads();",ob­j.T);

}
};
Má jen posouvat sidebar neustále na spodní hranu zobrazení.

Snažil jsem se fakt najít co je mezi těmito módy za rozdíl, dohledal jsem , že ve quirk módu Není nutné uvádět pixely u rozměrů a u ID nerozlišuje velká a malá písmena.
Opravdu už nevím na co se zaměřit, zkoušel jsem různé změny v CSS, ale opravdu nevím na co se zaměřit. Můžete někdo nasměrovat? dík

 
Odpovědět 6. listopadu 1:30
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 12. Zobrazit vše