JS进阶 | 原型和原型链解析

57 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

在 ES6 之前,JS 没有类和继承的概念,JS 是通过原型来实现继承的

一、原型

当我们声明一个函数function func() {}的时候,func实际上就是一个构造函数,每个函数都有一个属性:原型 prototype

func.prototype 的结构如下:

{ 
constructor: func(), 
_proto_: ...
}

在控制台查看:

  • prototype 是以 [[prototype]] 这种形式出现的,表示此属性是对象的内部属性,不能被直接访问。

  • constructor 属性,表示指向该原型实例的构造函数

  • proto 属性,指向构造方法的原型对象,每个实例对象都有一个_proto_ 属性

image.png

二、原型链

每个对象都有一个原型,原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链

  1. 每个对象的__proto__都是指向它的构造函数的原型对象prototype
  2. 原型链顶端是 Object.prototype
  3. 一切对象都是继承自Object对象,Object 对象直接继承null

function Fruits(name,color) {
   this.name = name;
   this.color = color;
}

var p = new Fruits("apple","red");
Fruits.prototype.address = "Hebei";

console.log(p.__proto__ === Fruits.prototype) // true
console.log(Fruits.prototype.constructor === Fruits) // true
console.log(p.constructor === Fruits) // true

打印 p ,可以看到如下结构:

image.png

原型链查找过程:

  • 当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有这个属性,就会去他的__proto__隐式原型上去找(即它的构造函数的 prototype)

  • 如果还找不到,就去原型的原型(即构造函数的prototype的__proto__)上去找,....

  • 一直找到最顶层(Object.prototype)为止

  • 如果还没有找到,则返回 undefined

三、 [ ] 的原型链是怎样的 ?

  • [].proto 指向 Array.prototype
  • Array.prototype.proto 指向 Object.prototype
  • Object.protytype.proto 的最终指向为 null

四、判断原型的方法

  • instanceof
  • in —— 管是不是在原型上,只要存在就是true
  • Object.hasOwnProperty —— 判断某个属性是否在自己上面(不是原型上,如果属性在原型上会返回 false)

具体实现可参考前文:手写系列 | instanceof 原理及实现