2013-05-19 8 views
5

Ich habe versucht, mit OO JavaScript in den Griff zu bekommen und ein einfaches Beispiel erstellt.OO JavaScript Aufruf Elternmethode

function BasePage(name) { 
    this.init(name); 
} 

BasePage.prototype = { 
    init: function(name) { 
     this.name = name; 
    }, 
    getName: function() { 
     return this.name; 
    } 
} 

function FaqPage (name, faq) { 
    this.init(name, faq); 
} 

FaqPage.prototype = new BasePage(); 

FaqPage.prototype = { 
    init: function(name, faq) { 
     BasePage.prototype.init.call(this, name); 
     this.faq = faq; 
    }, 
    getFaq: function() { 
     return this.faq; 
    } 
} 

var faqPage = new FaqPage('Faq Page', 'Faq'); 

var text = faqPage.getName() + ' ' + faqPage.getFaq(); 
$('body').text(text); 

Das Ergebnis läuft dies in der folgenden Meldung führt:

Uncaught TypeError: Object #<Object> has no method 'getName'

Was würde ich wissen, wie kann ich die Methode getName() in der Superklasse aufrufen, ohne es zu überschreiben, die rufen in der Unterklasse?

Auch wenn meine, wenn Sie denken, dieser Ansatz ist schlecht/gut.

Antwort

1

Ich fühle deinen Schmerz. Wie andere bereits erwähnt haben, ist getNameundefined, weil Sie die von FaqPage überschreiben. Daher werde ich diese Erklärung nicht wiederholen.

Das gesagt, ich stimme zu, dass es gut ist, Methoden in einem einzigen Bereich zu verkapseln. Vielleicht sollten Sie zu diesem Zweck eine JavaScript-Bibliothek verwenden. Der kleinste da draußen ist augment.In der Tat ist es nur 17 Zeilen lang:

Function.prototype.augment = function (body) { 
    var base = this.prototype; 
    var prototype = Object.create(base); 
    body.apply(prototype, Array.from(arguments, 1).concat(base)); 
    if (!Object.ownPropertyOf(prototype, "constructor")) return prototype; 
    var constructor = prototype.constructor; 
    constructor.prototype = prototype; 
    return constructor; 
}; 

(function funct() { 
    var bind = funct.bind; 
    var bindable = Function.bindable = bind.bind(bind); 
    var callable = Function.callable = bindable(funct.call); 
    Object.ownPropertyOf = callable(funct.hasOwnProperty); 
    Array.from = callable([].slice); 
}()); 

Hier ist, wie Ihr Code aussehen würde, wenn Sie augment verwendet:

var BasePage = Object.augment(function() { 
    this.constructor = function (name) { 
     this.name = name; 
    }; 

    this.getName = function() { 
     return this.name; 
    }; 
}); 

var FaqPage = BasePage.augment(function (base) { 
    this.constructor = function (name, faq) { 
     base.constructor.call(this, name); 
     this.faq = faq; 
    }; 

    this.getFaq = function() { 
     return this.faq; 
    }; 
}); 

Dann können Sie es, wie Sie verwenden normalerweise tun würde:

var faqPage = new FaqPage("Faq Page", "Faq"); 
var text = faqPage.getName() + " " + faqPage.getFaq(); 
$("body").text(text); 

Ich hoffe, das hilft.

+0

Danke Aadit, ich sehe Augment gut in der Benchmark, die Sie getan haben, aber was ist in Chrome passiert? Graph zeigte Null Operationen? – Stokedout

+0

@Stokedout - Benchmarks sollten mit einem Körnchen Salz genommen werden. Ohne Zweifel ist "Augment" schnell. Die meisten JavaScript-Programmierer sind jedoch Amateure, die schlampigen Code schreiben. Um dies zu kompensieren, optimieren die meisten JavaScript-Engines wie V8 stark. Das Ergebnis ist, dass sogar schlechter Code rasend schnell läuft (manchmal sogar schneller als guter Code, weil schlechte Entwurfsmuster gut optimiert sind). Aber das ist keine Entschuldigung, um schlechten Code zu schreiben. Guter Code ist nicht nur schnell, sondern auch lesbar, ausdrucksstark und leicht zu verstehen und zu pflegen. und "Augment" trifft alle diese Punkte. Es ist eigentlich schnell in Chrome 26. Langsam in 27. –

+0

Cool danke, meine Gründe für den Wechsel zu OO JS sind alles, was Sie gerade erwähnt haben. Ich kann nicht mit den Chrome-Versionen mithalten und kann es kaum abwarten, von den IE-Veröffentlichungen geschossen zu werden ;-). Ein letzter Kommentar zum obigen Code. Wenn ich Konstruktor verwende, dann ist init sicherlich eine Duplizierung derselben Sache? – Stokedout

6

Dieser Fehler tritt auf, weil, obwohl Sie den FaqPage-Prototyp als eine Instanz von BasePage festgelegt haben, Ihre nächste Zeile dies sofort überschreibt. So erbt FaqPage nicht von BasePage. Eigenschaften hinzufügen/Methoden FaqPage ‚s Prototyp statt es ein zweites Mal zu definieren:

FaqPage.prototype.init = function(name, faq) { 
    BasePage.prototype.init.call(this, name); 
    this.faq = faq; 
} 
FaqPage.prototype.getFaq = function() { 
    return this.faq; 
} 
+0

Danke, ich hatte das Gefühl, das wäre der Grund. Ist dies die einzige Möglichkeit, Methoden in OO JS hinzuzufügen? Für mich, die aus C# kommen, scheint es hässlich zu sein, Klassenmethoden in einem Bereich zu gruppieren. – Stokedout

+0

Ich weiß, was du meinst, aber ja, das ist der empfohlene Weg. Es kann auf dich wachsen. Denken Sie daran, dass Sie auch Methoden auf "BasePage" platzieren können. – sh0ber

2

Die erste Zeile ist richtig, Sie einen Prototyp aus dem Basisobjekt erstellen.

FaqPage.prototype = new BasePage(); 

Aber dann überschreiben Sie es, so tut, ist nicht das Basisobjekt erben mehr

FaqPage.prototype = { 
    init: function(name, faq) { 
     BasePage.prototype.init.call(this, name); 
     this.faq = faq; 
    }, 
    getFaq: function() { 
     return this.faq; 
    } 
} 

Statt den gesamten Prototyp definiert, außer Kraft setzen nur einzelne Funktionen:

FaqPage.prototype.init = function(name, faq) { 
    BasePage.prototype.init.call(this, name); 
    this.faq = faq; 
}; 

FaqPage.prototype.getFaq = function() { 
    return this.faq; 
}; 
1

Wenn Vererbung ist, was Sie suchen, es ist nicht sehr einfach, in JavaScript zu erreichen, soweit ich weiß. Ich habe diesen Ausschnitt von John Resig verwendet und es funktioniert wie ein Zauber. http://ejohn.org/blog/simple-javascript-inheritance/

In Ihrem Fall ist dies, wie es funktionieren würde,

Basepage

var BasePage = Class.extend({ 
    init: function(name){ 
    this.name = name; 
    }, 
getName: function(){ 
    return this.name; 
} 
}); 

FaqPage Klasse vererben Basepage

var FaqPage = BasePage.extend({ 
    init: function(name, faq){ 
    this._super(name); 
    this.faq = faq; 
    }, 
    getFaq: function() { 
    return this.faq; 
    } 
}); 

Und dann

var faqPage = new FaqPage('Faq Page', 'Faq'); 
var text = faqPage.getName() + ' ' + faqPage.getFaq(); 
$('body').text(text); 

Damit das funktioniert, müssen Sie natürlich den Implementierungscode auf der Seite einfügen, die ich verlinkt habe.

Hier ist die Geige, http://jsfiddle.net/c8yjY/

+0

John Resigs Code ist ein bisschen veraltet. Es gibt viele bessere OOP-Bibliotheken da draußen: http://jsperf.com/oop-benchmark/127 Bitte lesen Sie meine Antwort oben. –