概念
prototype:object that provides shared properties(属性) for other objects
prototype 描述的是两个对象之间的某种关系(其中一个,为另一个提供属性访问权限)。
隐式引用
Every object has an implicit reference (called the object’s prototype)
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 对象
属性查找路径
- 先查找构造函数实例里的属性或方法,如果有,立刻返回
如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回 ```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
<a name="EJR8i"></a>
# 原型继承
> 继承就是一个对象可以访问另一个对象中的属性和方法,在 JS 中通过原型和原型链来实现继承。
> JS 的对象中存在一个隐藏属性 __proto__(对象的原型 ->> prototype),继承就是把 _ _proto__ 指向内存中的另一个对象
![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)
- 显式继承
- 隐式继承
<a name="Efhif"></a>
## 显式原型继承
使用 Object.setPrototypeOf 或 Object.create 方法,直接继承另一个对象
- Object.setPrototypeOf
![微信截图_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)
- Object.create
![微信截图_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)
<a name="4TMFW"></a>
## 隐式原型继承
没有隐式继承,要继承原型的方法:
1. 创建空对象
1. 设置空对象的原型(另一个对象或 null)
1. 填充该对象(属性或方法)
```javascript
const obj = {};
Object.setPrototypeOf(obj, Object.prototype);
obj.name = "填充的属性或方法";
让用户无感知的完成创建对象、原型继承和属性初始化的过程
- 将某些函数称之为 constructor,专门用来做属性初始化
- 约定 constructor 函数,有一个特殊属性 prototype
- 让用户使用 new 关键字,去创建新对象,由 new 去实现上面代码的操作 ```javascript function User(name) { this.name = name; }
User.prototype = Object.create(Object.prototype);
const user = new User(“属性初始化”);
真正的隐式继承<br />普通函数创建时,自带了 prototype 属性,包含 constructor 一个字段,指向构造函数。<br />将 create, linking, initilize 等多个步骤耦合到一起。
```javascript
function User(name) {
this.name = name;
}
const user = new User("属性初始化");
user.constructor === User
Prototype-based inheritance VS Class-based inheritance
inherit 继承:一种垂直关联过程
- Prototype-based inheritance:继承数据、结构和行为
- Class-based inheritance:继承结构和行为,没有继承数据(data 由 instance 承载)
JS 中的 class 由 prototype 模拟,为了符合 class 的特性,prototype 继承数据的特性被屏蔽了(即数据只出现在实例上而非原型对象)
JS 中 prototype 的本质
一个以隐式引用作为存储方式,以点操作符和属性访问语句作为语法糖的单向链表