views:

143

answers:

3

EDIT: I posted before I thought everything out. Here is a better implementation of what was in my mind: http://stackoverflow.com/questions/3376188/javascript-inheritance-idea-part-2

Okay, so I've seen that the following is bad

function A() {
    this.variable = 7;
    this.method = function() { alert(this.variable); };
}

alpha = new A();
beta = new A();

because you're duplicating the method for each instance. However, why couldn't you do:

var A = new function() {
    this.variable = null;
    this.method = function() { alert(this.variable); };
};

var alpha = {variable: 8};
alpha.__proto__ = A;

var beta = {variable: 9};
beta.__proto__ = A;

Then you inherit the methods without wasting memory, and you can specify new instance variables.

Of course, I've never seen this pattern, so what's the obvious reason it's not used?

+2  A: 

The obvious reason it's not used is that you're creating the objects yourself instead of letting the constructor create them. If the constructor is changed to work differently later, your code could break.

A better solution would be

function A(value) {
    this.variable = value;
}

A.prototype.method = function() { alert(this.variable); };

Javascript already looks at the object's methods, then the object's prototype's methods, when figuring out what to call. So defining your method in A's prototype defines it for every A you will, or even already did, create.

cHao
I wasn't really looking at A as a constructor function.. moreso that it is an object instance itself, and alpha and beta use it as a prototype. A's method might change, but that is the intended result, as the change propagates to alpha and beta (it's more object to object inheritance than object from classes). I could have done var A = {variable: null, method: ...}; but then any variables local to A (var local = 3;) would be inherited as well, which is not intended. I guess I'm saying it's more like Crockford's Object.create method (not classical inheritance), but with private variables...
Nick
Well, that's another reason you don't see your pattern much. :) Classical inheritance is far more common, and more familiar to most programmers. Indeed, that's how I was thinking when i wrote my answer.
cHao
+2  A: 

I think you are looking for pure prototypical inheritance.

The ECMAScript 5th Edition standard introduced the Object.create method, this method creates an object that directly inherits from its first argument passed (which can be either null or an object).

For example:

var A = {
  variable: null,
  method : function () { alert(this.variable); };
};

var alpha = Object.create(A);
alpha.variable = 8; // or above `Object.create(A, {'variable': { value: 8 } });`

var beta = Object.create(A);
beta.variable = 9;

This method is available on the most recent browsers, however can be roughly emulated on an ECMAScript 3 implementation:

if (!Object.create) {
  Object.create = function (o) {
    if (arguments.length > 1) { throw Error('Second argument not supported'); }
    if (o === null) { throw Error('Cannot set a null [[Prototype]]'); }
    if (typeof o != 'object') { throw TypeError('Argument must be an object'); }
    function F(){}
    F.prototype = o;
    return new F;
  };
}

Note that there are some features that cannot be emulated on ES3, like the second argument, it expects a property descriptor like the descriptor used by the new Object.defineProperties method.

Also, Object.create allows you to create an object that doesn't inherit from any other object, by setting its [[Prototype]] to null

CMS
A: 

The main reason that pattern is not used is that the __ proto __ is not standard. Works with firefox/chrome. But doesn't work with IE.

Also, the code you suggested doesn't have a constructor. It assumes that you'll initialize the object with the correct structure.

Juan Mendes