Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simpler / better way to call shadowed prototype method?

I'm writing an object hierarchy in JavaScript, I would like to call a method on an object's parent when I've shadowed that method in the object.

E.g.:

var Base = function Base(msg) {
  this.msg = msg;
}
Base.prototype.log = function(){
  console.log("base log: " + this.msg);
}

var Sub = function Sub(msg) {
  Base.call(this, msg);
}

Sub.prototype = Object.create(Base.prototype);

Sub.prototype.log = function() {
  console.log("sub log");

  this.__proto__.__proto__.log.call(this); // This works but __proto__
  Object.getPrototypeOf(Object.getPrototypeOf(this)).log.call(this); // This works but is verbose
  super.log(); // This doesn't work
}

var sub = new Sub('hi');
sub.log();

See the three lines at the bottom of the Sub.prototype.log function - is there a better way to do what I'm trying to do there?

The second line is the best I've been able to come up with but is very verbose!

like image 757
sync Avatar asked Apr 29 '16 05:04

sync


People also ask

Is inheritance possible in JavaScript?

When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype.

How to create generic objects in JavaScript?

In JavaScript, there is the ability to create a generic anonymous object to serve this purpose. It can either be created using new Object() or the shorthand { ... } syntax, and can then be given any properties or methods that are needed.

Can we create class in JavaScript?

Class methods are created with the same syntax as object methods. Use the keyword class to create a class. Always add a constructor() method. Then add any number of methods.

What is instance in JS?

The instanceof operator in JavaScript is used to check the type of an object at run time. It returns a boolean value if true then it indicates that the object is an instance of a particular class and if false then it is not.


2 Answers

super is not defined, obviously it wouldn't work.

You might want to try:

Sub.prototype.log = function() {
  console.log("sub log");

  Base.prototype.log.call(this);
}

Another way is to use the following method to inherit classes:

function extend(Child, Parent) {
    var F = function() { };
    F.prototype = Parent.prototype;
    Child.prototype = new F();    

    // better to make it static (better practice in OOP world) 
    // e.g. Child.super = ...,
    // but in your case:
    Child.prototype.super = Parent.prototype;      
}

So here is an example:

// ..
extend(Sub, Base);

Sub.prototype.log = function() {
  console.log("sub log");

  this.super.log.call(this);
}

In case of ES6:

class Base {
  constructor(msg) {
    this.msg = msg;
  }

  log(){
    console.log("base log: " + this.msg);
  }
}

class Sub extends Base {
  constructor(msg) {
    super(msg);
  }

  log() {
    console.log("sub log");
    super.log();
  }
}

var sub = new Sub('hi');
sub.log();
like image 159
oleh.meleshko Avatar answered Nov 08 '22 05:11

oleh.meleshko


If you want to keep the original method without using the name Base you could capture it using a closure before you change it.

(function() {
   var superLog = Sub.prototype.log;
   Sub.prototype.log = function() {
       console.log("sub log");
       superLog();
   };
})();

This way there is no dependancy on how you inherit from Base.

Side note: the terminology you are looking for is 'overriding' the base method.

like image 23
mcfedr Avatar answered Nov 08 '22 03:11

mcfedr