[javascript] Calling method using JavaScript prototype

Is it possible to call the base method from a prototype method in JavaScript if it's been overridden?

MyClass = function(name){
    this.name = name;
    this.do = function() {
        //do somthing 
    }
};

MyClass.prototype.do = function() {  
    if (this.name === 'something') {
        //do something new
    } else {
        //CALL BASE METHOD
    }
};

This question is related to javascript prototype overriding

The answer is


function NewClass() {
    var self = this;
    BaseClass.call(self);          // Set base class

    var baseModify = self.modify;  // Get base function
    self.modify = function () {
        // Override code here
        baseModify();
    };
}

No, you would need to give the do function in the constructor and the do function in the prototype different names.


If you know your super class by name, you can do something like this:

function Base() {
}

Base.prototype.foo = function() {
  console.log('called foo in Base');
}

function Sub() {
}

Sub.prototype = new Base();

Sub.prototype.foo = function() {
  console.log('called foo in Sub');
  Base.prototype.foo.call(this);
}

var base = new Base();
base.foo();

var sub = new Sub();
sub.foo();

This will print

called foo in Base
called foo in Sub
called foo in Base

as expected.


Well one way to do it would be saving the base method and then calling it from the overriden method, like so

MyClass.prototype._do_base = MyClass.prototype.do;
MyClass.prototype.do = function(){  

    if (this.name === 'something'){

        //do something new

    }else{
        return this._do_base();
    }

};

I'm afraid your example does not work the way you think. This part:

this.do = function(){ /*do something*/ };

overwrites the definition of

MyClass.prototype.do = function(){ /*do something else*/ };

Since the newly created object already has a "do" property, it does not look up the prototypal chain.

The classical form of inheritance in Javascript is awkard, and hard to grasp. I would suggest using Douglas Crockfords simple inheritance pattern instead. Like this:

function my_class(name) {
    return {
        name: name,
        do: function () { /* do something */ }
    };
}

function my_child(name) {
    var me = my_class(name);
    var base_do = me.do;
    me.do = function () {
        if (this.name === 'something'){
            //do something new
        } else {
            base_do.call(me);
        }
    }
    return me;
}

var o = my_child("something");
o.do(); // does something new

var u = my_child("something else");
u.do(); // uses base function

In my opinion a much clearer way of handling objects, constructors and inheritance in javascript. You can read more in Crockfords Javascript: The good parts.


This solution uses Object.getPrototypeOf

TestA is super that has getName

TestB is a child that overrides getName but, also has getBothNames that calls the super version of getName as well as the child version

_x000D_
_x000D_
function TestA() {_x000D_
  this.count = 1;_x000D_
}_x000D_
TestA.prototype.constructor = TestA;_x000D_
TestA.prototype.getName = function ta_gn() {_x000D_
  this.count = 2;_x000D_
  return ' TestA.prototype.getName is called  **';_x000D_
};_x000D_
_x000D_
function TestB() {_x000D_
  this.idx = 30;_x000D_
  this.count = 10;_x000D_
}_x000D_
TestB.prototype = new TestA();_x000D_
TestB.prototype.constructor = TestB;_x000D_
TestB.prototype.getName = function tb_gn() {_x000D_
  return ' TestB.prototype.getName is called ** ';_x000D_
};_x000D_
_x000D_
TestB.prototype.getBothNames = function tb_gbn() {_x000D_
  return Object.getPrototypeOf(TestB.prototype).getName.call(this) + this.getName() + ' this object is : ' + JSON.stringify(this);_x000D_
};_x000D_
_x000D_
var tb = new TestB();_x000D_
console.log(tb.getBothNames());
_x000D_
_x000D_
_x000D_


Another way with ES5 is to explicitely traverse the prototype chain using Object.getPrototypeOf(this)

const speaker = {
  speak: () => console.log('the speaker has spoken')
}

const announcingSpeaker = Object.create(speaker, {
  speak: {
    value: function() {
      console.log('Attention please!')
      Object.getPrototypeOf(this).speak()
    }
  }
})

announcingSpeaker.speak()

If I understand correctly, you want Base functionality to always be performed, while a piece of it should be left to implementations.

You might get helped by the 'template method' design pattern.

Base = function() {}
Base.prototype.do = function() { 
    // .. prologue code
    this.impldo(); 
    // epilogue code 
}
// note: no impldo implementation for Base!

derived = new Base();
derived.impldo = function() { /* do derived things here safely */ }

I know this post is from 4 years ago, but because of my C# background I was looking for a way to call the base class without having to specify the class name but rather obtain it by a property on the subclass. So my only change to Christoph's answer would be

From this:

MyClass.prototype.doStuff.call(this /*, args...*/);

To this:

this.constructor.prototype.doStuff.call(this /*, args...*/);

function MyClass() {}

MyClass.prototype.myMethod = function() {
  alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
  MyClass.prototype.myMethod_original.call( this );
  alert( "doing override");
};

myObj = new MyClass();
myObj.myMethod();

An alternative :

// shape 
var shape = function(type){
    this.type = type;
}   
shape.prototype.display = function(){
    console.log(this.type);
}
// circle
var circle = new shape('circle');
// override
circle.display = function(a,b){ 
    // call implementation of the super class
    this.__proto__.display.apply(this,arguments);
}

if you define a function like this (using OOP)

function Person(){};
Person.prototype.say = function(message){
   console.log(message);
}

there is two ways to call a prototype function: 1) make an instance and call the object function:

var person = new Person();
person.say('hello!');

and the other way is... 2) is calling the function directly from the prototype:

Person.prototype.say('hello there!');

In addition, if you want to override all instances and not just that one special instance, this one might help.

function MyClass() {}

MyClass.prototype.myMethod = function() {
  alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
  MyClass.prototype.myMethod_original.call( this );
  alert( "doing override");
};

myObj = new MyClass();
myObj.myMethod();

result:

doing original
doing override

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to prototype

What are the nuances of scope prototypal / prototypical inheritance in AngularJS? Extending an Object in Javascript __proto__ VS. prototype in JavaScript Parse JSON String into a Particular Object Prototype in JavaScript Understanding the difference between Object.create() and new SomeFunction() 'this' is undefined in JavaScript class methods JavaScript: What are .extend and .prototype used for? Calling method using JavaScript prototype Use of 'prototype' vs. 'this' in JavaScript?

Examples related to overriding

How to underline a UILabel in swift? How to 'update' or 'overwrite' a python list maven command line how to point to a specific settings.xml for a single command? How to override the properties of a CSS class using another CSS class What is the difference between dynamic and static polymorphism in Java? Overriding css style? Android Overriding onBackPressed() What is the 'override' keyword in C++ used for? Why do we have to override the equals() method in Java? Can overridden methods differ in return type?