72158e7b

Локальные и наследуемые значения



Локальные и наследуемые значения

Когда Вы выполняете доступ к свойству объекта, 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 имеет одно локальное свойство, projects. Значения свойств name и dept не являются локальными по отношению к amy и поэтому получены из свойства __proto__ объекта amy.
Таким образом, amy имеет следующие значения свойств:

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

Теперь предположим, что Вы изменяете значение свойства name в прототипе, ассоциированном с Employee:

Employee.prototype.name = "Unknown"

На первый взгляд можно ожидать, что новое значение передаётся всем экземплярам Employee. Однако это не так.

Когда Вы создаёте любой экземпляр объекта Employee, этот экземпляр получает локальное значение свойства name (пустую строку). Это означает, что, если Вы устанавливаете прототип WorkerBee через создание нового объекта Employee, WorkerBee.prototype имеет локальное значение для свойства name. Следовательно, когда JavaScript ищет свойство name объекта amy (экземпляра WorkerBee), 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";

Теперь свойство name объекта amy становится "Unknown".

Как видно из этих примеров, если Вы хотите иметь значения по умолчанию для свойств объекта и хотите иметь возможность изменять значения по умолчанию на этапе прогона программы, Вы должны устанавливать свойства в прототипе конструктора, а не в самой функции-конструкторе.



Содержание раздела