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;

3
  • Prototypal inheritance in javascript requires either the new operator or Object.create. You're using neither here. Commented Feb 9, 2014 at 1:07
  • That doesn't look like a constructor. You'd use the constructor with new. It looks more like a module pattern. Commented Feb 9, 2014 at 1: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 stackoverflow.com/a/16063711/1641941 Commented Feb 9, 2014 at 2:56

1 Answer 1

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?
Sign up to request clarification or add additional context in comments.

3 Comments

Note: a better way to establish inheritance is to use Object.create(Parent.prototype) not new Parent. stackoverflow.com/a/17393153/218196 edit: Ah that's what you are doing in your defclass function :D
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 Maybe someone new to JavaScript would benefit more from learning Haskell. Seriously, learning Haskell makes you a better JavaScript programmer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.