Details of the object model 对象与继承

本贴最后更新于 3176 天前,其中的信息可能已经事过景迁

基于(类 vs 原型)的语言

JavaScript is an object-based language based on prototypes, rather than being class-based.

JS 是一种基于原型的面向对象语言,而不是基于类的。

A prototype-based language, such as JavaScript, does not make this distinction: it simply has objects. A prototype-based language has the notion of a prototypical object, an object used as a template from which to get the initial properties for a new object. Any object can specify its own properties, either when you create it or at run time. In addition, any object can be associated as the prototype for another object, allowing the second object to share the first object's properties.

基于原型的语言具有所谓原型对象(prototypical object)的概念。原型对象可以作为一个模板,新对象可以从中获得原始的属性。任何对象都可以指定其自身的属性,既可以是创建时也可以在运行时创建。而且,任何对象都可以作为另一个对象的原型(prototype),从而允许后者共享前者的属性。

雇员示例

目标结构:

 

实现过程: figure8.2.png

定义对象: figure8.3.png

继承的另一种途径是使用call() / apply() 方法。下面的方式都是等价的:

function Engineer (name, projs, mach) {
  this.base = WorkerBee;
  this.base(name, "engineering", projs);
  this.machine = mach || "";
}
 
function Engineer (name, projs, mach) {
  WorkerBee.call(this, name, "engineering", projs);
  this.machine = mach || "";
}
 

使用 javascript 的 call() 方法相对明了一些,因为无需 base 方法了。

 

判断实例的关系

JavaScript 的属性查找机制首先在对象自身的属性中查找,如果指定的属性名称没有找到,将在对象的特殊属性 __proto__ 中查找。这个过程是递归的;被称为“在原型链中查找”。

特殊的 __proto__ 属性是在构建对象时设置的;设置为构造器的 prototype 属性的值。所以表达式 new Foo() 将创建一个对象,其 __proto__ == Foo.prototype。因而,修改 Foo.prototype 的属性,将改变所有通过 new Foo() 创建的对象的属性的查找。

每个对象都有一个 __proto__ 对象属性(除了 Object);每个函数都有一个 prototype 对象属性。因此,通过“原型继承(prototype inheritance)”,对象与其它对象之间形成关系。通过比较对象的 __proto__ 属性和函数的 prototype 属性可以检测对象的继承关系。JavaScript 提供了便捷方法:instanceof 操作符可以用来将一个对象和一个函数做检测,如果对象继承自函数的原型,则该操作符返回真。例如:

var f = new Foo();
var isTrue = (f instanceof Foo);

没有多继承

某些面向对象语言支持多重继承。也就是说,对象可以从无关的多个父对象中继承属性和属性值。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.prototype.equipment = ["mask", "fins", "regulator", "bcd"]

假设添加了一个属性到 Hobbyist 构造器的原型:dennis 对象不会继承这个新属性。

 

 

  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    710 引用 • 1173 回帖 • 192 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...