emepyc
emepyc

Reputation: 969

Prototype chain in Javascript not updated

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;

Upvotes: 2

Views: 99

Answers (1)

Aadit M Shah
Aadit M Shah

Reputation: 74204

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?

Upvotes: 2

Related Questions