|
|
(One intermediate revision by the same user not shown) |
Line 1: |
Line 1: |
| 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.
| | See [http://developer.mozilla.org/en/docs/Differential_inheritance_in_JavaScript Differential inheritance in JavaScript] at [http://developer.mozilla.org MDC]. |
|
| |
|
| 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.
| | [[Category:Redirects]] |
| | |
| <pre>
| |
| Object.prototype.clone = function(){
| |
| var newObject = new this.constructor();
| |
| newObject.__proto__ = this;
| |
| return newObject;
| |
| };
| |
| | |
| Root = new Object();
| |
| </pre>
| |
| | |
| 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.
| |
| | |
| <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>
| |
| | |
| ===Words of caution===
| |
| | |
| *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.
| |
| | |
| *Also note that when you change the <code>Object</code> prototype, <i>all</i> javascript objects are affected. While this is what you wanted, there is a gotcha: when it comes to object property enumeration, the <code>for( variable in object )</code> iterator will also see your inherited function, and any code using the basic object as an associative array and iterating it like this without safeguarding from inherited properties (<code>Object</code> has no inherited enumerable properties by default) will most likely break. If your code lives in a vacuum where it will never affect code invented elsewhere and you still want to use both of these techniques, you can rewrite this iteration to avoid inherited properties using the <code>__proto__</code> property mentioned in the first gotcha above:
| |
| | |
| <pre>
| |
| for( variable in object )
| |
| if( object.__proto__[variable] !== object[variable] )
| |
| { /* your loop body here instead */ }
| |
| </pre>
| |
| | |
| [[Category:Example code]] [[Category:JavaScript example code]]
| |