JavaScript 常被描述为一种基于原型的语言 (prototype-based language)
每一个对象都有一个原型对象,对象已其为模板继承属性和方法。
原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype
属性上,而非对象实例本身。
prototype 属性:继承成员被定义的地方
原因在于,继承的属性和方法是定义在 prototype
属性之上的(你可以称之为子命名空间 (sub namespace) )——那些以 Object.prototype.
开头的属性,而非仅仅以 Object.
开头的属性。prototype
属性的值是一个对象,我们希望被原型链下游的对象继承的属性和方法,都被储存在其中。
于是 [Object.prototype.watch()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/watch)、``[Object.prototype.valueOf()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf)
等等成员,适用于任何继承自 Object()
的对象类型,包括使用构造器创建的新的对象实例。[Object.is()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
、[Object.keys()](https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys)
,以及其他不在 prototype
对象内的成员,不会被“对象实例”或“继承自 Object()
的对象类型”所继承。这些方法/属性仅能被 Object()
构造器自身使用。
实例对象, 原型对象, 构造函数关系
create()
我们曾经讲过如何用 [Object.create()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
方法创建新的对象实例。
例如,在上个例子的 JavaScript 控制台中输入:
var person2 = Object.create(person1);
create()
实际做的是从指定原型对象创建一个新的对象。这里以person1
为原型对象创建了person2
对象。在控制台输入:person2.__proto__
constructor 属性
每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。
例如,在控制台中尝试下面的指令:
person1.constructor
person2.constructor
都将返回
Person()
构造器,因为该构造器包含这些实例的原始定义。
一个小技巧是,你可以在constructor
属性的末尾添加一对圆括号(括号中包含所需的参数),从而用这个构造器创建另一个对象实例。毕竟构造器是一个函数,故可以通过圆括号调用;只需在前面添加new
关键字,便能将此函数作为构造器使用。