mozilla

Revision 70198 of Differential inheritance in JavaScript

  • Revision slug: Differential_inheritance_in_JavaScript
  • Revision title: Differential inheritance in JavaScript
  • Revision id: 70198
  • Created:
  • Creator: Np
  • Is current revision? No
  • Comment copied from mz with section in "Words of caution" rewritten because of licensing
Tags: 

Revision Content

Netscape 4.x and Mozilla both provide access to the internal prototype information associated with an Object in Javascript using the __proto__ property. By manipulating this property, a developer can emulate "differential inheritance", a common technique in prototype-oriented programming models.

Differential Inheritance is a common prototype-oriented model that uses the concept that most objects are derived from other, more generic objects, and only differ in a few small aspects. Each object maintains a reference to its prototype and a table of properties that are different. The following code provides a simple method for "cloning" an object and a fundamental object, since the global variable Object actually refers to the Object constructor, not an actual Object.

Object.prototype.clone = function(){
  var newObject = new this.constructor();
  newObject.__proto__ = this;
  return newObject;
};

Root = new Object();

Using "clone", it becomes possible to simply derive more specific objects from a generic prototype. The following is a simple example of building up increasingly more specific objects using the clone method and differential inheritance.

Record = Root.clone();
Record.toString = function(){ return "a Record"; };
 
Person = Root.clone();
Person.firstName = false;
Person.lastName = false;
Person.toString = function(){ 
    if( this.firstName ){
      if( this.lastName ){
        return this.firstName + " " +this.lastName; 
      }else{
        return this.firstName;
      }
    }else{
      if( this.lastName ){
        return this.lastName;
      }else{
        return "a Person";
    }
  }
}
 
JoePerson = Person.clone();
JoePerson.firstName = "Joe";
alert( JoePerson.toString() );

Words of caution

Internet Explorer currently does not support the __proto__ property. It is recommended that this technique be reserved for situations where the developer can be certain that the script will be executed by Mozilla or other interpreters that support the __proto__ property, like Safari and KJS.

When changing the Object prototype, all JavaScript objects are affected since they all inherit from it. This will change the behaviour of object property enumeration to include the new functions and properties added. You can work around this in your code by the method below, but scripts not under your control won't have this work around.

for(i in object) {
  if(object.__proto__[i] != object[i]) { ) //no built-in object properties and functions are inherited
    /* normal code here */
  } else {
    /* special code for your new properties and functions */
  }
}

Revision Source

<p>Netscape 4.x and Mozilla both provide access to the internal prototype information associated with an Object in Javascript using the <code>__proto__</code> property. By manipulating this property, a developer can emulate "differential inheritance", a common technique in prototype-oriented programming models.
</p><p>Differential Inheritance is a common prototype-oriented model that uses the concept that most objects are derived from other, more generic objects, and only differ in a few small aspects. Each object maintains a reference to its prototype and a table of properties that are different. The following code provides a simple method for "cloning" an object and a fundamental object, since the global variable Object actually refers to the Object constructor, not an actual Object.
</p>
<pre>Object.prototype.clone = function(){
  var newObject = new this.constructor();
  newObject.__proto__ = this;
  return newObject;
};

Root = new Object();
</pre>
<p>Using "clone", it becomes possible to simply derive more specific objects from a generic prototype. The following is a simple example of building up increasingly more specific objects using the clone method and differential inheritance.
</p>
<pre>Record = Root.clone();
Record.toString = function(){ return "a Record"; };
 
Person = Root.clone();
Person.firstName = false;
Person.lastName = false;
Person.toString = function(){ 
    if( this.firstName ){
      if( this.lastName ){
        return this.firstName + " " +this.lastName; 
      }else{
        return this.firstName;
      }
    }else{
      if( this.lastName ){
        return this.lastName;
      }else{
        return "a Person";
    }
  }
}
 
JoePerson = Person.clone();
JoePerson.firstName = "Joe";
alert( JoePerson.toString() );
</pre>
<h4 name="Words_of_caution">Words of caution</h4>
<p>Internet Explorer currently does not support the <code>__proto__</code> property. It is recommended that this technique be reserved for situations where the developer can be certain that the script will be executed by Mozilla or other interpreters that support the <code>__proto__</code> property, like Safari and KJS.
</p><p>When changing the Object prototype, all JavaScript objects are affected since they all inherit from it. This will change the behaviour of object property enumeration to include the new functions and properties added. You can work around this in your code by the method below, but scripts not under your control won't have this work around.
</p>
<pre>for(i in object) {
  if(object.__proto__[i] != object[i]) { ) //no built-in object properties and functions are inherited
    /* normal code here */
  } else {
    /* special code for your new properties and functions */
  }
}
</pre>
Revert to this revision