Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OO JavaScript call parent method

Tags:

javascript

oop

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.

like image 616
Stokedout Avatar asked May 19 '13 15:05

Stokedout


3 Answers

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;
}
like image 122
Dan Avatar answered Sep 27 '22 00:09

Dan


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;
};
like image 26
claustrofob Avatar answered Sep 24 '22 00:09

claustrofob


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.

like image 43
Aadit M Shah Avatar answered Sep 24 '22 00:09

Aadit M Shah