文章

原型和原型链理解

原型和原型链理解

原型和原型链理解

原型和原型链理解

要知道:所有对象都是通过 ****new** 创建的**

原型

每个函数都有 prototype 属性 称之为原型,因为这个属性的值是个对象,也称之为 原型对象

作用:

  1. 存放一些属性和方法,共享给实例对象使用
  2. 在 javascript 中实现继承(ES5)

ES6中增加了 class 类,使用 extends 关键字实现继承

**proto每个对象都有一个 **proto 属性,这个属性指向它的原型对象

例:

1
2
3
const arr = new Array(1, 2, 3)
arr.sort() // 排序
arr.reverse() // 反转

我们通过 new Array() 这个构造函数创建了一个数组 arr,为什么 arr 这个数组可以使用 sort、reverse 等方法呢,其实就是因为我们原型的存在。

分析

1704854214981-4bb94b28-61b2-4d50-866b-2d13c30b5226.png

array 构造函数也是一个函数,只要是函数它就会有一个原型(Array.prototype)

在 JS 中,这个原型已经挂载了很多方法(我们在查一些数组的方法时候 在mdn站中前面都加上了 prototype,这些方法都是挂载在构造函数的原型身上),也就是说原型本身就有这些方法


通过构造函数生成实例 arrarr 就可以使用 prototype 原型身上这些方法(上面说到 每个对象都有一个 proto 属性,这个属性指向它的原型对象)所以就有 arr 的 proto 等价 Array.prototype(arr.proto** **=== Array.prototype),

原型链

1704855560910-238ceef4-5d1c-47a0-bf54-5e707cb118ce.png

1
2
3
4
5
6
7
8
9
10
11
function Person() {
    console.log(1)
}
Person.prototype.name = 'bob'
let person = new Person()
// person.__proto__ 指向 Person.prototype
console.log(person.__proto__, person.__proto__ === Person.prototype) // {name: "bob", [[Prototype]]: Object} true
// person.__proto__.__proto__ 指向Object.prototype
console.log(person.__proto__.__proto__) // {}
// 下面 Object.prototype 指向了 null
console.log(person.__proto__.__proto__.__proto__) // null

分析上图:

我们创建一个构造函数叫 Person,只要是函数他就有一个 prototype(原型:共享一些属性和方法);

然后通过 new 创建了一个对象实例 person,只要是对象他就有一个 __proto__ (指向上面这个原型)

所以我这个 person 对象就可以使用这个原型身上的一些属性和方法了,如果这个原型里面没有这些属性和方法,它就会接着往上一层去找(因为 prototype 也是对象,只要是对象就有一个 __proto__ 指向了更上一级,此时找到最大的对象 Object 的原型)

由于 Object.prototype 也是一个对象,那这个对象里面也有 __proto__ ,所以再往上面找,这时候发现已经没有了 所以就返回了 null

通过 __proto__ 一层层的去找原型,当前原型身上没有 我再到更高一级上面的这个原型身上去找,如果还没有找到再往上照,直到返回结果或 null 为止,那这条线路就称之为 原型链

总结:

对象都有一个 proto 属性,这个属性指向它的原型对象,原型对象也是对象,也有 proto 属性 指向原型对象的原型对象,这样一层层形成的**链式结构称为原型链,**最顶层找不到则返回null。

本文由作者按照 CC BY 4.0 进行授权