js原型成员和实例成员

大多数 JavaScript 代码以面向对象的形式编写。无论通过创建自定义对象还是使用内置的对象,诸如文 档对象模型(DOM)和浏览器对象模型(BOM)之中的对象。因此,存在很多对象成员访问。

对象成员

对象成员包括属性和方法,在 JavaScript 中,二者差别甚微。对象的一个命名成员可以包含任何数据类 型。既然函数也是一种对象,那么对象成员除传统数据类型外,也可以包含一个函数。当一个命名成员引 用了一个函数时,它被称作一个“方法”,而一个非函数类型的数据则被称作“属性”。

正如本章前面所讨论过的,对象成员比直接量或局部变量访问速度慢,在某些浏览器上比访问数组项还 要慢。要理解此中的原因,首先要理解 JavaScript 中对象的性质。

JavaScript 中的对象是基于原形的。原形是其他对象的基础,定义并实现了一个新对象所必须具有的成 员。这一概念完全不同于传统面向对象编程中“类”的概念,它定义了创建新对象的过程。原形对象为所有 给定类型的对象实例所共享,因此所有实例共享原形对象的成员。

一个对象通过一个内部属性绑定到它的原形。Firefox,Safari,和 Chrome 向开发人员开放这一属性,称 作proto;其他浏览器不允许脚本访问这一属性。任何时候你创建一个内置类型的实例,如 Object 或 Array,这些实例自动拥有一个 Object 作为它们的原形。
因此,对象可以有两种类型的成员:实例成员(也称作“own”成员)和原形成员。实例成员直接存在于 实例自身,而原形成员则从对象原形继承。考虑下面的例子:

1
2
3
4
5
var book = {
title: "High Performance JavaScript",
publisher: "Yahoo! Press"
};
alert(book.toString()); //"[object Object]"

此代码中,book 对象有两个实例成员:title 和 publisher。注意它并没有定义 toString()接口,但是这个 接口却被调用了,也没有抛出错误。toString()函数就是一个 book 对象继承的原形成员。

处理对象成员的过程与变量处理十分相似。当 book.toString()被调用时,对成员进行名为“toString”的搜 索,首先从对象实例开始,如果 book 没有名为 toString 的成员,那么就转向搜索原形对象,在那里发现了 toString()方法并执行它。通过这种方法,booke 可以访问它的原形所拥有的每个属性或方法。

你可以使用 hasOwnProperty()函数确定一个对象是否具有特定名称的实例成员,(它的参数就是成员名 称)。要确定对象是否具有某个名称的属性,你可以使用操作符 in。

1
2
3
4
5
6
7
8
9
var book = {
title: "High Performance JavaScript",
publisher: "Yahoo! Press"
};

alert(book.hasOwnProperty("title")); //true
alert(book.hasOwnProperty("toString")); //false
alert("title" in book); //true
alert("toString" in book); //true

此代码中,hasOwnProperty()传入“title”时返回 true,因为 title 是一个实例成员。传入“toString”时返回 false, 因为 toString 不在实例之中。如果使用 in 操作符检测这两个属性,那么返回都是 true,因为它既搜索实例 又搜索原形。