局域值和繼承值

局域值和繼承值

當你存取物件屬性的時候,JavaScript 會進行這些步驟,如同本章前面所提到過的︰

  1. 檢查局域值是否存在。如果存在,就返回局域值。
  2. 如果局域值不存在,就檢查原型鏈(使用 __proto__ 屬性)。
  3. 如果在原型鏈上的物件具有所求的指定屬性,就返回這個屬性的值。
  4. 如果找不到這樣的屬性,這個物件就不具有這個屬性。

這些步驟之後的結果,取決於你如何循著這個方式來定義。一開始的例子有這些定義︰

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

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

藉由這些定義,假定你以如下語句建立 amy 作為 WorkerBee 的實體︰

amy = new WorkerBee;

amy 物件具有一個局域的屬性,projectsnamedept 屬性的值並不是 amy 的局域值,所以是從 amy 物件的 __proto__ 屬性得來的。因此,amy 具有這些屬性值︰

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

現在假定你在與 Employee 連結的原型改變 name 屬性的值︰

Employee.prototype.name = "Unknown"

乍看之下,你可能會預期新的值會被向下傳播給 Employee 所有的實體。然而,事情並不如此。

當你建立 Employee 物件的任何實體,這些實體會取得 name 屬性的局域值(空字串的那個)。這意味著當你使用新建立的 Employee 物件來設定 WorkerBee 原型的時候,WorkerBee.prototype 就具有 name 屬性的局域值。因此,當 JavaScript 找到 amy 物件(WorkerBee 的實體)的 name 屬性的時候,JavaScript 在 WorkerBee.prototype 找到了這些屬性的局域值。也因此並不會進一步在鏈的上一層 Employee.prototype 裡尋找。

如果你想要在執行時期改變物件屬性的值,而且希望新的值能被這個物件的所有子孫所繼承,你就不能在物件的建構子函數中定義這個屬性。相對的,你要把這個屬性加入到與建構子相連結的原型。例如,假定你修改前面的代碼如下︰

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

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

amy = new WorkerBee;

Employee.prototype.name = "Unknown";

在這個情況下,amyname 屬性就會變成 "Unknown"。

如同這些範例所示,如果你希望物件的屬性有預設值,而且還希望能夠在執行時期修改這些預設值,你就應該在建構子的原型中設定這些屬性,而不是在建構子函數本身。

文件標籤與貢獻者

 此頁面的貢獻者: teoli, happysadman
 最近更新: teoli,