Javascript Privilege Function Inheritance

ossys

I have spent the past few weeks doing a ton of research on Javascript inheritance. Firstly, I want to say that I am NOT trying to implement class-based inheritance in Javascript, however, I am trying to mimic inheritance CORRECTLY using Javascript's prototypal nature. This may be beating a dead horse, but here goes my question:

I have two simple functions:

function Animal(arg) {
    var a = arg;

    //privileged function has access to private variable
    this.sayHi = function(name) {
        // can access a here if needed
        console.log('Hi: ' + name);
    }
}

and:

function Person(arg) {
    this.sayHi = function(name) {
        super.sayHi(name + '!!!');
    };
}

Person.inheritsFrom(Animal);

The following would be the expected result:

var animal = new Animal('cow');
animal.sayHi('John'); // Hi: John

var person = new Person('adult');
person.sayHi('Fred'); // Hi: Fred!!!

The "inheritsFrom()" method that I'm using for inheritance looks like:

Function.prototype.inheritsFrom = function(parent) {
    if(parent.constructor == Function) { //Normal Inheritance
        this.prototype = new parent;
        this.prototype.constructor = this;
        this.prototype.parent = parent.prototype;
    } else  { //Pure Virtual Inheritance
        this.prototype = parent;
        this.prototype.constructor = this;
        this.prototype.parent = parent;
    }
    return this;
}

These are some of my references: http://phrogz.net/JS/classes/OOPinJS2.html http://www.crockford.com/javascript/inheritance.html https://medium.com/javascript-scene/common-misconceptions-about-inheritance-in-javascript-d5d9bab29b0a

Lots of good info, still can't figure out how to inherit "privileged" methods as shown above. I'm able to call the privileged method of the parent class. Please see the following JS Fiddle: https://jsfiddle.net/jxjk5hm9/

Any guidance on inheriting privileged methods is greatly appreciated, thanks!

Felix Kling

There is no pretty solution to this. First off,

 this.prototype = new parent;

is not a good way to establish inheritance. Rather use

 this.prototype = Object.create(parent.prototype);

See Benefits of using `Object.create` for inheritance for more info.

Inside the child constructor, you'd have to call the parent constructor, applying it to the current instance:

function Person(arg) {
    Animal.call(this, arg);
}

then you have to iterate over all methods that have been attached to this by Animal and keep a reference to them:

function Person(arg) {
    Animal.call(this, arg);
    var privilegedSuper = Object.keys(this)
      .filter(function(prop) { return typeof this[prop] === 'function'; }.bind(this))
      .reduce(function(obj, prop) { return (obj[prop] = this[prop]), obj; }.bind(this));
}

which you can then reference in the overridden methods:

function Person(arg) {
    Animal.call(this, arg);
    var privilegedSuper = Object.keys(this)
      .filter(function(prop) { return typeof this[prop] === 'function'; }.bind(this))
      .reduce(function(obj, prop) { return (obj[prop] = this[prop]), obj; }.bind(this));

    this.sayHi = function(name) {
      privilegedSuper.sayHi.call(this, name + '!!!');
    };
}

Is it worth the effort and the complexity? I don't think so.

Function.prototype.inheritsFrom = function(parent) {
  if (parent.constructor == Function) { //Normal Inheritance
    this.prototype = Object.create(parent.prototype);
    this.prototype.constructor = this;
    this.prototype.parent = parent.prototype;
  } else { //Pure Virtual Inheritance
    this.prototype = parent;
    this.prototype.constructor = this;
    this.prototype.parent = parent;
  }
  return this;
}

function Animal(arg) {
  var a = arg;

  //privileged function has access to private variable
  this.sayHi = function(name) {
    // can access a here if needed
    console.log('Hi: ' + name + ' (and here is a: ' + a + ')');
  }
}

function Person(arg) {
  Animal.call(this, arg);
  var privilegedSuper = Object.keys(this)
    .filter(function(prop) {
      return typeof this[prop] === 'function';
    }.bind(this))
    .reduce(function(obj, prop) {
      return (obj[prop] = this[prop]), obj;
    }.bind(this), {});

  this.sayHi = function(name) {
    privilegedSuper.sayHi.call(this, name + '!!!');
  };
}
Person.inheritsFrom(Animal);

var animal = new Animal('cow');
animal.sayHi('John'); // Hi: John

var person = new Person('adult');
person.sayHi('Fred'); // Hi: Fred!!!

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related