概念

prototype:object that provides shared properties(属性) for other objects

prototype 描述的是两个对象之间的某种关系(其中一个,为另一个提供属性访问权限)。

隐式引用

Every object has an implicit reference (called the object’s prototype)

微信截图_20210220115456.png

ECMAScript 规范描述 prototype 是一个隐式引用,但浏览器中可以通过 obj.proto 这个显式的属性访问到被定义为隐式属性的 prototype。

prototype chain 原型链

a prototype may have a non-null(非空) implicit reference to its prototype, and so on; this is called the prototype chain.

即,prototype 对象也有自己的隐式引用,有自己的 prototype 对象

属性查找路径

  1. 先查找构造函数实例里的属性或方法,如果有,立刻返回
  2. 如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回 ```javascript const lookupProperty = (object, propertyName) => { let current = object;

    if (current == null) { throw new Error(Cannot read property '${propertyName}' of '${object}'); }

    while (current) { if (current.hasOwnProperty(propertyName)) { return current[propertyName]; }

    current = Object.getPrototypeOf(current); }

    return undefined; }

console.log(‘equal’, lookupProperty({}, ‘toString’) === Object.prototype.toString); // equal true

  1. <a name="EJR8i"></a>
  2. # 原型继承
  3. > 继承就是一个对象可以访问另一个对象中的属性和方法,在 JS 中通过原型和原型链来实现继承。
  4. > JS 的对象中存在一个隐藏属性 __proto__(对象的原型 ->> prototype),继承就是把 _ _proto__ 指向内存中的另一个对象
  5. ![63bd704eb45646e2f46af426196a3d88.jpg](https://cdn.nlark.com/yuque/0/2021/jpeg/651859/1615987694319-ae656ecb-9e3f-42f1-85b8-a44be03373c2.jpeg#align=left&display=inline&height=662&margin=%5Bobject%20Object%5D&name=63bd704eb45646e2f46af426196a3d88.jpg&originHeight=662&originWidth=1142&size=111637&status=done&style=none&width=1142)
  6. - 显式继承
  7. - 隐式继承
  8. <a name="Efhif"></a>
  9. ## 显式原型继承
  10. 使用 Object.setPrototypeOf 或 Object.create 方法,直接继承另一个对象
  11. - Object.setPrototypeOf
  12. ![微信截图_20210220144112.png](https://cdn.nlark.com/yuque/0/2021/png/651859/1613803285767-b93c137c-2e94-4c4d-a7db-45c962c90337.png#align=left&display=inline&height=421&margin=%5Bobject%20Object%5D&name=%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210220144112.png&originHeight=421&originWidth=407&size=19255&status=done&style=none&width=407)
  13. - Object.create
  14. ![微信截图_20210220144228.png](https://cdn.nlark.com/yuque/0/2021/png/651859/1613803362756-7084dab9-7b26-4770-8bab-6fb7bff86af9.png#align=left&display=inline&height=382&margin=%5Bobject%20Object%5D&name=%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210220144228.png&originHeight=382&originWidth=407&size=17941&status=done&style=none&width=407)
  15. <a name="4TMFW"></a>
  16. ## 隐式原型继承
  17. 没有隐式继承,要继承原型的方法:
  18. 1. 创建空对象
  19. 1. 设置空对象的原型(另一个对象或 null)
  20. 1. 填充该对象(属性或方法)
  21. ```javascript
  22. const obj = {};
  23. Object.setPrototypeOf(obj, Object.prototype);
  24. obj.name = "填充的属性或方法";

让用户无感知的完成创建对象、原型继承和属性初始化的过程

  1. 将某些函数称之为 constructor,专门用来做属性初始化
  2. 约定 constructor 函数,有一个特殊属性 prototype
  3. 让用户使用 new 关键字,去创建新对象,由 new 去实现上面代码的操作 ```javascript function User(name) { this.name = name; }

User.prototype = Object.create(Object.prototype);

const user = new User(“属性初始化”);

  1. 真正的隐式继承<br />普通函数创建时,自带了 prototype 属性,包含 constructor 一个字段,指向构造函数。<br />将 create, linking, initilize 等多个步骤耦合到一起。
  2. ```javascript
  3. function User(name) {
  4. this.name = name;
  5. }
  6. const user = new User("属性初始化");
  7. user.constructor === User

微信截图_20210220151156.png

Prototype-based inheritance VS Class-based inheritance

inherit 继承:一种垂直关联过程

  • Prototype-based inheritance:继承数据、结构和行为
  • Class-based inheritance:继承结构和行为,没有继承数据(data 由 instance 承载)

JS 中的 class 由 prototype 模拟,为了符合 class 的特性,prototype 继承数据的特性被屏蔽了(即数据只出现在实例上而非原型对象)
微信截图_20210220153904.png

JS 中 prototype 的本质

一个以隐式引用作为存储方式,以点操作符和属性访问语句作为语法糖的单向链表

资料

  1. 深入理解 JS 原型
  2. 05|原型链:V8是如何实现对象继承的?