原型prototype

230 阅读3分钟

JS是一门基于原型一切皆对象的弱类型语言,简单来说JS只有一种数据结构就是对象,由于JS没有类(class),所以JS是通过构造函数来实现类

构造函数:实现类的一种方式,可以理解为声明了一个创造事务的设计图,本身不具备任何具像化的东西,仅仅是一个声明,如果需要确定真正的实物则需要实例化,也就是创造一个真正的人比如小明

  • 本质还是函数,继承了函数本来的方法或属性,比如call等
  • 每个构造函数都有一个对应的原型对象,通过prototype指针可以获取,原型对象反过来有一个constructor指针指向构造函数本身
  • 通过new操作可以生成此“类”的实例,每个实例都有一个内在属性__proto__隐式绑定对应的构造函数的原型
function Person(){} //构造人的函数

const proto = Person.prototype //有一个指向构造函数原型的prototype指针
proto.constructor = Person //原型有一个只想构造函数的指针

const XiaoMing = new Person()
XiaoMing.__proto__ === Person.prototype 
//true, 实例的有一个隐式绑定原型的指针__proto__,指向构造函数原型

原型链

  • JS一切皆对象,所有的对象都是某个构造函数的实例,也就有一个__proto__绑定指向构造函数的原型
  • 原型对象也是对象,同样也有一个__proto__指向更高一级的构造函数原型
  • 原型链的顶端是Object.prototype,他的__proto__ = null
  • 在某个对象访问某个属性/方法的时候,首先在当前对象上查找否则就在原型上找,如果找不到就到__proto__指向的父级原型对象上查找,如果找到则返回,否则继续向上查找直到顶级Object.prototype
function Person(){}
const XiaoMing = new Person()

XiaoMing.__proto__ => Person.prototype.__proto__ => Object.prototype.__proto__ = null
//当前实例的原型链路

JS原生的构造函数,Array,String,Number,Function等

  • 由于原生此类存在,JS内部常用的变量,比如字符串,数组等其实都是此类构造函数的实例,所以常用变量的__proto__都执行对应构造函数的prototype,比如数组就原型就保存着常用的一些方法,比如pop,push等
  • 由于此类构造函数的本质还是函数,所以他们也是Function构造函数的实例,所以Array,String等的__proto__是指向Function.prototype
  • Function.prototype,由于JS系统为了解决一些兼容的问题,JS吧Function.prototype设计成了一个函数对象,也就是说Function.prototype返回的是一个函数,由于函数也是对象,所以内部可以绑定一些属性和方法,比如函数常用的call等
  • 简单来说Function构造函数也是Function的实例所以也就有了Function.proto = Function.prototype
  • Function.prototype的绑定proto则是指向最高Object.prototype
const arr = []
arr.__proto__ = Array.prototype //数组构造函数有很多数组的常用方法
Array.__proto__ === Function.prototype //构造函数Array原型的隐式绑定到Function的原型
Function.prototype() 
//undefined,返回的是一个函数对象,所以可以直接执行,但是返回没有任何返回值,
//由于函数可以有自己的属性,所以很多函数方法绑定在这个函数对象上
Function.prototype.__proto__ === Object.prototype //函数的原型依旧只想最高