I've been trying to get to grips with OO JavaScript and created a simple example.
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);
The result of running this results in the following message:
Uncaught TypeError: Object
#<Object>
has no method 'getName'
What I would like to know is how can I call the method getName()
in the super class without having to override and call it in the sub class?
Also if my if you think this approach is bad/good.
That error occurs because even though you've set FaqPage
's prototype to be an instance of BasePage
, your next line immediately overwrites that. So FaqPage
is not inheriting from BasePage
. Add properties/methods to FaqPage
's prototype instead of defining it a second time:
FaqPage.prototype.init = function(name, faq) {
BasePage.prototype.init.call(this, name);
this.faq = faq;
}
FaqPage.prototype.getFaq = function() {
return this.faq;
}
The first line is right, you create a prototype from the base object.
FaqPage.prototype = new BasePage();
But then you override it, so is does not inherit the base object anymore
FaqPage.prototype = {
init: function(name, faq) {
BasePage.prototype.init.call(this, name);
this.faq = faq;
},
getFaq: function() {
return this.faq;
}
}
Instead of defining the entire prototype, override just individual functions:
FaqPage.prototype.init = function(name, faq) {
BasePage.prototype.init.call(this, name);
this.faq = faq;
};
FaqPage.prototype.getFaq = function() {
return this.faq;
};
I feel your pain. As others have mentioned getName
is undefined
because you override the prototype
of FaqPage
. Hence I'll not reiterate that explanation.
That being said I do agree that it's good to encapsulate prototype
methods in a single scope. Perhaps you should use a JavaScript library for this purpose. The smallest one out there is augment. In fact it's only 17 lines long:
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);
}());
Here's how your code would look if you used augment
:
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;
};
});
Then you may use it as you normally would:
var faqPage = new FaqPage("Faq Page", "Faq");
var text = faqPage.getName() + " " + faqPage.getFaq();
$("body").text(text);
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With