- 本地值和继承值。在访问一个对象的属性时,JavaScript 将执行下面的步骤:
(1)检查本地值是否存在。如果存在,返回该值。
(2)如果本地值不存在,检查原型链(通过 Proto属性)。
(3)如果原型链中的某个对象具有指定属性的值,则返回该值。
(4)如果这样的属性不存在,则对象没有该属性。
- 判断实例的关系。JavaScript 的属性查找机制首先在对象自身的属性中查找,如果指定的属性名称没有找到,将在对象的特殊属性 proto 中查找。这个过程是递归的;被称为“在原型链中查找”。
特殊的 proto 属性是在构建对象时设置的;设置为构造器的 prototype 属性的值。所以表达式 new Foo() 将创建一个对象,其 proto == Foo.prototype。因而,修改 Foo.prototype 的属性,将改变所有通过 new Foo() 创建的对象的属性的查找。
每个对象都有一个 proto 对象属性(除了 Object);每个函数都有一个 prototype对象属性。因此,通过“原型继承”,对象与其它对象之间形成关系。通过比较对象的 proto 属性和函数的 prototype 属性可以检测对象的继承关系。JavaScript 提供了便捷方法:instanceof 操作符可以用来将一个对象和一个函数做检测,如果对象继承自函数的原型,则该操作符返回真。
- JS不支持多重继承。某些面向对象语言支持多重继承。也就是说,对象可以从无关的多个父对象中继承属性和属性值。JavaScript 不支持多重继承。
JavaScript 属性值的继承是在运行时通过检索对象的原型链来实现的。因为对象只有一个原型与之关联,所以 JavaScript 无法动态地从多个原型链中继承。
在 JavaScript 中,可以在构造器函数中调用多个其它的构造器函数。这一点造成了多重继承的假象。例如,考虑如下语句:
function Hobbyist (hobby) {this.hobby = hobby || "scuba";}function Engineer (name, projs, mach, hobby) {this.base1 = WorkerBee;this.base1(name, "engineering", projs);this.base2 = Hobbyist;this.base2(hobby);this.machine = mach || "";}Engineer.prototype = new WorkerBee;var dennis = new Engineer("Doe, Dennis", ["collabra"], "hugo")
进一步假设使用本章前面所属的 WorkerBee 的定义。此时 dennis 对象具有如下属性:
dennis.name == "Doe, Dennis"dennis.dept == "engineering"dennis.projects == ["collabra"]dennis.machine == "hugo"dennis.hobby == "scuba"
dennis 确实从 Hobbyist 构造器中获得了 hobby 属性。但是,假设添加了一个属性到 Hobbyist 构造器的原型:
Hobbyist.prototype.equipment = ["mask", "fins", "regulator", "bcd"]
dennis 对象不会继承这个新属性。
