Local versus Inherited Values

  • Revision slug: JavaScript/Guide/Obsolete_Pages/Property_Inheritance_Revisited/Local_versus_Inherited_Values
  • Revision title: Local versus Inherited Values
  • Revision id: 117568
  • Created:
  • Creator: Mchenryc
  • Is current revision? No
  • Comment /* Local versus Inherited Values */ fix typo: "=" != "=="

Revision Content

Local versus Inherited Values

When you access an object property, JavaScript performs these steps, as described earlier in this chapter:

  1. Check to see if the value exists locally. If it does, return that value.
  2. If there is not a local value, check the prototype chain (using the __proto__ property).
  3. If an object in the prototype chain has a value for the specified property, return that value.
  4. If no such property is found, the object does not have the property.

The outcome of these steps depends on how you define things along the way. The original example had these definitions:

function Employee () {
this.name = "";
this.dept = "general";
}

function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;

With these definitions, suppose you create amy as an instance of WorkerBee with the following statement:

amy = new WorkerBee;

The amy object has one local property, projects. The values for the name and dept properties are not local to amy and so are gotten from the amy object's __proto__ property. Thus, amy has these property values:

amy.name == "";
amy.dept == "general";
amy.projects == [];

Now suppose you change the value of the name property in the prototype associated with Employee:

Employee.prototype.name = "Unknown"

At first glance, you might expect that new value to propagate down to all the instances of Employee. However, it does not.

When you create any instance of the Employee object, that instance gets a local value for the name property (the empty string). This means that when you set the WorkerBee prototype by creating a new Employee object, WorkerBee.prototype has a local value for the name property. Therefore, when JavaScript looks up the name property of the amy object (an instance of WorkerBee), JavaScript finds the local value for that property in WorkerBee.prototype. It therefore does not look farther up the chain to Employee.prototype.

If you want to change the value of an object property at run time and have the new value be inherited by all descendants of the object, you cannot define the property in the object's constructor function. Instead, you add it to the constructor's associated prototype. For example, assume you change the preceding code to the following:

function Employee () {
   this.dept = "general";
}
Employee.prototype.name = "";

function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;

amy = new WorkerBee;

Employee.prototype.name = "Unknown";

In this case, the name property of amy becomes "Unknown".

As these examples show, if you want to have default values for object properties and you want to be able to change the default values at run time, you should set the properties in the constructor's prototype, not in the constructor function itself.

{{template.PreviousNext("Core_JavaScript_1.5_Guide:Property_Inheritance_Revisited", "Core_JavaScript_1.5_Guide:Property_Inheritance_Revisited:Determining_Instance_Relationships")}}

{{ wiki.languages( { "ja": "ja/Core_JavaScript_1.5_Guide/Property_Inheritance_Revisited/Local_versus_Inherited_Values", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Powr\u00f3t_dziedziczenia_w\u0142a\u015bciwo\u015bci/Warto\u015bci_lokalne_vs._dziedziczone" } ) }}

Revision Source

<div class="noinclude"></div>
<h3 name="Local_versus_Inherited_Values"> Local versus Inherited Values </h3>
<p>When you access an object property, JavaScript performs these steps, as described earlier in this chapter:
</p>
<ol><li> Check to see if the value exists locally. If it does, return that value.
</li><li> If there is not a local value, check the prototype chain (using the <code>__proto__</code> property).
</li><li> If an object in the prototype chain has a value for the specified property, return that value.
</li><li> If no such property is found, the object does not have the property.
</li></ol>
<p>The outcome of these steps depends on how you define things along the way. The original example had these definitions:
</p>
<pre>function Employee () {
this.name = "";
this.dept = "general";
}

function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;
</pre>
<p>With these definitions, suppose you create <code>amy</code> as an instance of <code>WorkerBee</code> with the following statement:
</p>
<pre>amy = new WorkerBee;
</pre>
<p>The amy object has one local property, projects. The values for the name and dept properties are not local to amy and so are gotten from the amy object's <code>__proto__</code> property. Thus, amy has these property values:
</p>
<pre>amy.name == "";
amy.dept == "general";
amy.projects == [];
</pre>
<p>Now suppose you change the value of the <code>name</code> property in the prototype associated with <code>Employee</code>:
</p>
<pre>Employee.prototype.name = "Unknown"
</pre>
<p>At first glance, you might expect that new value to propagate down to all the instances of <code>Employee</code>. However, it does not.
</p><p>When you create <i>any</i> instance of the Employee object, that instance gets a local value for the name property (the empty string). This means that when you set the <code>WorkerBee</code> prototype by creating a new <code>Employee</code> object, <code>WorkerBee.prototype</code> has a local value for the name property. Therefore, when JavaScript looks up the name property of the amy object (an instance of WorkerBee), JavaScript finds the local value for that property in WorkerBee.prototype. It therefore does not look farther up the chain to Employee.prototype.
</p><p>If you want to change the value of an object property at run time and have the new value be inherited by all descendants of the object, you cannot define the property in the object's constructor function. Instead, you add it to the constructor's associated prototype. For example, assume you change the preceding code to the following:
</p>
<pre>function Employee () {
   this.dept = "general";
}
Employee.prototype.name = "";

function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;

amy = new WorkerBee;

Employee.prototype.name = "Unknown";
</pre>
<p>In this case, the name property of amy becomes "Unknown".
</p><p>As these examples show, if you want to have default values for object properties and you want to be able to change the default values at run time, you should set the properties in the constructor's prototype, not in the constructor function itself.
</p>
<div class="noinclude">
<p>{{template.PreviousNext("Core_JavaScript_1.5_Guide:Property_Inheritance_Revisited", "Core_JavaScript_1.5_Guide:Property_Inheritance_Revisited:Determining_Instance_Relationships")}}
</p>
</div>
{{ wiki.languages( { "ja": "ja/Core_JavaScript_1.5_Guide/Property_Inheritance_Revisited/Local_versus_Inherited_Values", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Powr\u00f3t_dziedziczenia_w\u0142a\u015bciwo\u015bci/Warto\u015bci_lokalne_vs._dziedziczone" } ) }}
Revert to this revision