如何理解 JS 原型和原型链(隐式原型和显示原型)

1.原型

ES6中的 class 是一个语法糖,class实际上是一个函数。

// 父类(基类)
class People {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
console.log(this.name);
}
}

// 子类使用 extends 关键字 实现继承
class Programmer extends People {
constructor(name, type) {
// super() 调用父类的构造函数
super(name);
this.type = type;
}
code() {
console.log(${this.name} is 正在写代码);
}
job() {
console.log(${this.name} is ${this.type});
}
}

const Gown = new Programmer('Gown', '前端工程师');
typeof People; // function
typeof Programmer; // function

显示原型和隐示原型

// 显示原型和隐示原型
console.log(Programmer.prototype); //People { sayName: [Function: sayName] }
console.log(Gown.__proto__); //People { sayName: [Function: sayName] }
console.log(Gown.__proto__ === Programmer.prototype); //true

!image-20220609113927000

基于原型的执行规则

>1.获取属性John.name 或执行 sayName()方法
>2.先获取属性自身的属性和方法
>3.找不到自动通过隐示原型去查找

2.原型链

Gown.hasOwnProperty('name'); //true
Gown.hasOwnProperty('sayName()'); //false
Gown.hasOwnProperty('hasOwnProperty()'); //false

当我们「读取」John.hasOwnProperty 时,JS 引擎会做下面的事情:

1. 看看 Gown对象本身有没有 hasOwnProperty 属性。没有就走到下一步。
2. 如果 Gown.__proto__ 没有,那么浏览器会继续查看 Gown.__proto__.__proto__
3. 如果 Gown.__proto__.__proto__ 也没有,那么浏览器会继续查看 Gown.__proto__.__proto__.proto__
4. 直到找到 hasOwnProperty 或者 __proto__ 为 null。

上面的过程,就是「读」属性的「搜索过程」。

而这个「搜索过程」,是连着由 __proto__ 组成的链子一直走的。

这个链子,就叫做「原型链」。

!image-20220609121416345

> Object.prototype的隐式原型,_proto__永远指向null