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() 构造器自身使用。

实例对象, 原型对象, 构造函数关系

image.png

create()

我们曾经讲过如何用 [Object.create()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create) 方法创建新的对象实例。

  1. 例如,在上个例子的 JavaScript 控制台中输入:

    1. var person2 = Object.create(person1);
  2. create() 实际做的是从指定原型对象创建一个新的对象。这里以 person1 为原型对象创建了 person2 对象。在控制台输入:

    1. person2.__proto__

    结果返回对象person1

    constructor 属性

    每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。

  3. 例如,在控制台中尝试下面的指令:

    1. person1.constructor
    2. person2.constructor
  4. 都将返回 Person() 构造器,因为该构造器包含这些实例的原始定义。
    一个小技巧是,你可以在 constructor 属性的末尾添加一对圆括号(括号中包含所需的参数),从而用这个构造器创建另一个对象实例。毕竟构造器是一个函数,故可以通过圆括号调用;只需在前面添加 new 关键字,便能将此函数作为构造器使用。