Autor | Zpráva | ||
---|---|---|---|
Joker Profil |
#1 · Zasláno: 18. 9. 2015, 10:48:21
Přemýšlím nad následujícím zápisem:
var myNS = { Foo : function() { this.hello = function () { alert("Ahoj!"); }; } , Bar : function() { var obj = new myNS.Foo(); obj.bye = function() { alert("Tak zatím!"); }; return obj; } }; var test = new myNS.Bar(); test.hello(); test.bye(); Objekt Bar vlastně dědí od objektu Foo tím způsobem, že v konstruktoru vyrobí objekt Foo, rozšíří ho o další vlastnosti a ten výsledek vrátí jako sebe. A ptám se větších expertů na OOP v JavaScriptu, než jsem já: Je to dobrý, nebo špatný přístup? |
||
Radek9 Profil |
Joker:
Ona tohle technicky vzato dědičnost není, pořád to je objekt, který přímo dědí z Foo.prototype . (Tedy test instanceof myNS.Bar bude false.) Je to jen jakýsi obal kolem konstruktoru. Nicméně se nedá říct, že je to špatný způsob. Mnohdy to úplně stačí a je to nejjednodušší řešení. Za předpokladu, že bys ale chtěl skutečnou dědičnost, se to řeší přes zdědění prototypu:
function Foo() { // … } Foo.prototype.hello = function () { alert("Ahoj!"); }; function Bar() { // … } Bar.prototype = Object.create(Foo.prototype); Bar.prototype.constructor = Bar; Bar.prototype.bye = function () { alert("Tak zatím!"); }; var test = new Bar(); test.hello(); test.bye(); test instanceof Foo; // true test instanceof Bar; // true Tohle řešení má navíc výhodu v tom, že reaguje i na pozdější změny obou prototypů: test.prop; // undefined Foo.prototype.prop = 1; test.prop; // 1 Bar.prototype.prop = 2; test.prop; // 2 |
||
1Pupik1989 Profil |
#3 · Zasláno: 18. 9. 2015, 22:14:46
Je to špatný způsob. Vytvoříš totiž objekt, který se rázem zahodí, protože nemá využití, jelikož z konstruktoru vracíš jiný objekt. Když zavoláš jen
new Bar , tak dostaneš stejný výsledek. Já dědičnost píšu trochu jiným stylem.
Bar.prototype = (function(){ function F(){}; F.prototype = Foo.prototype; return new F; }();; Promiň, píšu to z telefonu, ale snad je princip jasný. |
||
Radek9 Profil |
#4 · Zasláno: 18. 9. 2015, 22:31:26
1Pupik1989:
„Je to špatný způsob. Vytvoříš totiž objekt, který se rázem zahodí“ To dnešním enginům nedělá zas takový problém. Vytvořit prázdný objekt zabere opravdu jen málo výpočetního času. V aplikaci se ti beztak válí hromada nepotřebných objektů, o které se časem postará garabage collector. Ale rozhodně bych neřekl, že je to špatný způsob. Jedná-li se o drobné rozšíření, u kterého nehrozí, že by se muselo při běhu aplikace rozšiřovat, tak je to naprosto v pořádku. |
||
_es Profil |
#5 · Zasláno: 19. 9. 2015, 07:37:56
Joker:
Nevýhodou je, že pre každý objekt sa vytvárajú odlišné objekty funkcií pre obe metódy aj hellou aj bye .
|
||
1Pupik1989 Profil |
Radek9:
Je to zbytečný zlozvyk. Hlavně nikde se nic nedědí. Další nevýhodou je, že při každém vytvoření objektu se znovu definují metody. var myNS = { Foo:function(){}, Bar:function(){} }; myNS.Foo.prototype.hello = function(){ alert('Ahoj'); }; myNS.Bar.prototype = (function(){ function F(){}; F.prototype = myNS.Foo.prototype; return new F; })(); myNS.Bar.prototype.bye = function(){ alert('Tak zatím!'); }; var test = new myNS.Bar(); test.hello(); test.bye(); test instanceof myNS.Bar; //true test instanceof myNS.Foo; //true Ve výkonu je to hodně znatelné. http://jsperf.com/constructors-djpw |
||
Radek9 Profil |
#7 · Zasláno: 19. 9. 2015, 11:11:33
_es, 1Pupik1989:
„pre každý objekt sa vytvárajú odlišné objekty funkcií pre obe metódy“ „při každém vytvoření objektu se znovu definují metody.“ Což zase až tak nevadí, v některých případech je to dokonce rychlejší. A zrovna tohle jde vyřešit tak, že se metoda definuje zvlášť a k objektu se přiřadí její reference. function bye() { alert("Tak zatím!"); } function Bar() { var obj = new Foo(); obj.bye = bye; return obj; } 1Pupik1989: „Je to zbytečný zlozvyk. Hlavně nikde se nic nedědí.“ Už jsem uváděl, že to dědičnost ve skutečnosti není. Ale rozhodně bych to neoznačil za zlozvyk. V JS je přehršel návrhových vzorů a nedá se jednoznačně říct, který je nejlepší. Vždy záleží na situaci, v mnoha případech je dědičnost naprosto zbytečná. |
||
Joker Profil |
Díky za komentáře a za tu myšlenku s testem rychlosti.
Zkoušel jsem to a dost se to liší podle prohlížeče. U Webkitů (Chrome a spol.) je zdá se rychlejší closure. Ve staré Opeře je naopak rychlejší spíš použití prototypu (přičemž v některých testech byl prototyp ve staré Opeře rychlejší, než jakákoliv varianta v novém prohlížeči) a v IE 10 to vychází podobně. Ještě přidám další poznatky ohledně výkonu: Varianta, se na nový objekt věší předem připravené funkce (closure 2) vychází konzistentně jako nejpomalejší (trochu překvapivě, řekl bych, ale dost podstatně, většinou o řád pomalejší). Při vytváření konzistentně (a asi logicky) vítězí prototyp, práce s objektem závisí na prohlížeči. A IE 10 je skoro všude asi o řád pomalejší, než Chrome a stará Opera. |
||
Časová prodleva: 9 let
|
0