2

I'm trying to understand prototypal inheritance in Javascript, but failing to apply to the following case. Any help would be appreciated.

I'm defining a constructor as follows:

var base = function() {
    var priv = "private"; // Private
    var publ = "public";  // Public through a getter/setter (below)

    // The object to return
    var f = {};

    f.publ = function (new_val) {
        if (!arguments.length) {
          return publ;
        }
        publ = new_val;
        return f;
    };

    return f;
};

With this constructor, I can create objects by calling base();. These objects have a public method (publ).

Now, following the same structure, I would like to have a new constructor that creates objects that inherits from objects created by the "base constructor" defined above:

var myclass = function () {

  // Other parameters defined here

  var f = function () {
      // publ is inherited
      console.log(f.publ());
  };

  // Trying to set the prototype of f to the object created by "base()"
  f.prototype = base();

  // Other methods defined here

  return f;
};

With f.prototype = base(); I want to make f inherit all the methods that are defined in the object returned by base(), but trying to call f.publ complains because f doesn't have method publ

Any help in understanding what is going on would be welcome

M;

emepyc
  • 949
  • 1
  • 10
  • 23
  • Prototypal inheritance in javascript requires either the `new` operator or `Object.create`. You're using neither here. – Eric Feb 09 '14 at 01:07
  • That doesn't look like a constructor. You'd use the constructor with `new`. It looks more like a module pattern. – elclanrs Feb 09 '14 at 01:07
  • As noted in several comments, use Object.create to set up prototype part of inheritance and do Parent.call(this,args) in Child (that will take care of inheriting instace members from Parent). More info here http://stackoverflow.com/a/16063711/1641941 – HMR Feb 09 '14 at 02:56

1 Answers1

2

The most common way to do prototypal inheritance is as follows:

function Base() {
    var priv = "private";
    this.publ = "public";
}

You can now create instances of Base using new Base. Next we create MyClass:

MyClass.prototype = new Base;

function MyClass() {
    alert(this.publ);
}

Finally you can create instance of MyClass using new MyClass as follows:

var a = new MyClass; // alerts "public"

See the demo for yourself: http://jsfiddle.net/b3QyE/


Prototypal inheritance in JavaScript can get a little confusing because it's constructor-centric instead of prototype-centric which is why I prefer using the following utility function to create "classes":

function defclass(base, body) {
    var uber = base.prototype;
    var prototype = Object.create(uber);
    var constructor = (body.call(prototype, uber), prototype.constructor);
    constructor.prototype = prototype;
    return constructor;
}

Using defclass you can now restructure your code as follows:

var Base = defclass(Object, function () {
    this.constructor = function () {
        var priv = "private";
        this.publ = "public";
    };
});

var MyClass = defclass(Base, function (uber) {
    this.constructor = function () {
        uber.constructor.call(this);
        alert(this.publ);
    };
});

It's much more readable and understandable. Everything is encapsulated within a single function scope and nothing is dangling out of place. In addition you don't need to understand prototypal inheritance to use it. See the updated demo: http://jsfiddle.net/b3QyE/2/

If you notice we're calling the Base class constructor function from the MyClass constructor. This allows you to initialize the instance using the Base class constructor. You can call any method of the Base class via uber.


To learn more about prototypal inheritance take a look at the following answers:

  1. JavaScript inheritance and the constructor property
  2. How to achieve pseudo-classical inheritance right on the class declaration?
  3. Benefits of prototypal inheritance over classical?
Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • 3
    Note: a better way to establish inheritance is to use `Object.create(Parent.prototype)` not `new Parent`. http://stackoverflow.com/a/17393153/218196 *edit:* Ah that's what you are doing in your `defclass` function :D – Felix Kling Feb 09 '14 at 02:29
  • You're quoting Crockford, a man that to this date hasn't been able to produce an article or presentation that correctly uses what he himself calls"pseudo classical inheritance" maybe someone new to JavaScript would benefit more from correct documentation about how to use constructor functions and prototype so they can decide for themselfs how to use or not use it. – HMR Feb 09 '14 at 03:09
  • @HMR Maybe someone new to JavaScript would benefit more from learning Haskell. Seriously, learning Haskell makes you a better JavaScript programmer. – Aadit M Shah Feb 09 '14 at 03:21