Search

10/22/2008

JavaScript's class-less objects by Stoyan Stefanov

JavaScript's class-less objects by Stoyan Stefanov
By convention, though, constructor functions are named with a capital letter to distinguish visually from normal functions and methods.

So which way is better - object literal or constructor function? Well, that depends on your specific task. For example, if you need to create many different, yet similar objects, then the class-like constructors may be the right choice. But if your object is more of a one-off singleton, then object literal is definitely simpler and shorter.

(Actually in JavaScript pretty much everything is an object, with the exception of the few primitive data types - string, boolean, number and undefined. Functions are objects, arrays are objects, even null is an object. Furthermore, the primitive data types can also be converted and used as objects, so for example "string".length is valid.)

Inheritance via the prototype
Here's a constructor function which will be the parent:

function NormalObject() {
this.name = 'normal';
this.getName = function() {
return this.name;
};
}

Now a second constructor:
function PreciousObject(){
this.shiny = true;
this.round = true;
}

PreciousObject.prototype = new NormalObject();

Notice how we needed to create an object with new and assign it to the prototype, because the prototype is just an object. It's not like one constructor function inherited from another, in essence we inherited from an object. JavaScript doesn't have classes that inherit from other classes, here objects inherit from other objects.
If you have several constructor functions that will inherit NormalObject objects, you may create new NormalObject() every time, but it's not necessary. Even the whole NormalObject constructor may not be needed. Another way to do the same would be to create one (singleton) normal object and use it as a base for the other objects.
var normal = {
name: 'normal',
getName: function() {
return this.name;
}
};

PreciousObject.prototype = normal;

Inheritance by copying properties
var shiny = {
shiny: true,
round: true
};

var normal = {
name: 'name me',
getName: function() {
return this.name;
}
};

function extend(parent, child) {
for (var i in parent) {
child[i] = parent[i];
}
}

extend(normal, shiny); // inherit
shiny.getName(); // "name me"

function begetObject(o) {
function F() {}
F.prototype = o;
return new F();
}

Parent object:

var normal = {
name: 'name me',
getName: function() {
return this.name;
}
};

A new object inheriting from the parent:
var shiny = begetObject(normal);


Augment the new object with more functionality:
shiny.round = true;
shiny.preciousness = true;

YUI's extend()
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
}


/**
* Utility to set up the prototype, constructor and superclass properties to
* support an inheritance strategy that can chain constructors and methods.
* Static members will not be inherited.
*
* @method extend
* @static
* @param {Function} subc the object to modify
* @param {Function} superc the object to inherit
* @param {Object} overrides additional properties/methods to add to the
* subclass prototype. These will override the
* matching items obtained from the superclass
* if present.
*/
extend: function(subc, superc, overrides) {
if (!superc||!subc) {
throw new Error("extend failed, please check that " +
"all dependencies are included.");
}
var F = function() {};
F.prototype=superc.prototype;
subc.prototype=new F();
subc.prototype.constructor=subc;
subc.superclass=superc.prototype;
if (superc.prototype.constructor == Object.prototype.constructor) {
superc.prototype.constructor=superc;
}

if (overrides) {
for (var i in overrides) {
if (L.hasOwnProperty(overrides, i)) {
subc.prototype[i]=overrides[i];
}
}

L._IEEnumFix(subc.prototype, overrides);
}
},

  • there are no classes
  • objects inherit from objects
  • object literal notation var o = {};
  • constructor functions provide Java-like syntax var o = new Object();
  • functions are objects
  • all function objects have a prototype property
    v And finally, there are dozens of ways to inmplement inheritance, you can pick and choose depending on your task at hand, personal preferences, team preferences, mood or the current phase of the Moon.

  • 沒有留言: