Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crockford Prototypical Inheritance... no prototype chain? No super?

Trying to understand a little more about Crockford's approach to Prototypical Inheritance whereby he essentially eliminates the constructor, thus eliminating any real possibility for a prototype chain or leveraging the idea of "super".

mynamespace.object.create = function( o ) {
    function F(){};
    F.prototype = o;
    return new F();
};

Is that intentional based on the theory behind prototypical?

The reason I ran into this is I wanted to create a base class with an init method that did some common jquery stuff (these methods are designed for automating creating a jquery plugin from an object a la www.alexsexton.com/?p=51)

As an example, I don't want to repeat this in every one of my init methods this.options = $.extend({},this.options,options);

So I wanted to have that in a base init, override the init in my extended objects, and then call this.prototype.init within the override to take care of that repeated stuff.

The object.create piece doesn't seem to let me do that in any way. Am I missing something here?

like image 866
Bob Spryn Avatar asked Jan 22 '23 16:01

Bob Spryn


1 Answers

The technique is centered on the prototype chain, this type of inheritance is also known as differential inheritance.

For example:

var obj = {};
var obj1 = Object.create(obj);
var obj2 = Object.create(obj1);

The prototype chain of obj2 looks like this:

           --------        --------         ------------------
 obj2 ---> | obj1 | -----> | obj  | -----> | Object.prototype | -----> null
           --------        -------          ------------------

The arrow that connects the objects in the above example is the internal [[Prototype]] property, and that forms the prototype chain.

When you try to access a property, for example in obj2, it will be searched along all the objects on the prototype chain until is found, otherwise the property accessor will simply yield undefined

The concept of super doesn't really exist, although there are ways to know the [[Prototype]] of an object.

The ECMAScript 5th Edition introduced the Object.getPrototypeOf method, for example:

Object.getPrototypeOf(obj2) === obj1; // true

However this method is not widely supported yet (along with the standard Object.create).

Some implementations provide access to an object's [[Prototype]] through the __proto__ property, e.g.:

obj2.__proto__ === obj1; // true

But remember that __proto__ is non-standard.

The isPrototypeOf method, part of ECMAScript 3, allows you to know if an object is in the prototype chain of another, e.g.:

obj1.isPrototypeOf(obj2);             // true
obj.isPrototypeOf(obj2);              // true
Object.prototype.isPrototypeOf(obj2); // true

In conclusion, a property is resolved as soon is found in the prototype chain, and if you want to avoid __proto__ and Object.getPrototypeOf (since the first is non-standard and the former is not widely supported yet), I would simply recommend you to prefix your init method in the base object, so it can be accessible from the more specific instances, e.g.:

var base = {
  baseInit: function () { /*...*/ }
};

var specific = Object.create(base);
specific.init = function () {
  //...
  this.baseInit();
  //...
};

specific.init();
like image 150
Christian C. Salvadó Avatar answered Jan 24 '23 07:01

Christian C. Salvadó