概念
原型链:每个实例对象都有一个私有属性__proto__指向实例的构造函数的原型对象(prototype),该原型对象也有自己的原型对象(proto),层层向上,直到原型对象是null为止,这种链型结构称为原型链 原型:每一个javascript对象创建的时候都会有一个与之关联的对象,这个对象就是原型,创建的对象从原型中继承方法和属性
首先我们先用一个构造函数创建一个实例对象 首先我们先说说什么是构造函数,其实构造函数和普通函数在创建上没有任何区别,只不过调用方式不一样而已,而且构造函数大部分使用大写字母开头,举个例子
function Demo(){}
const D = new Demo()
function demo(){}
const d = demo()
function Demo(){
this.name = 'xx'
}
const demo = new Demo()
console.log(demo.name) // xx
这个例子Demo就是构造函数,demo就是实例
prototype
每一个函数都会有一个prototype,并指向其实例对象的原型,那什么是原型呢? 每一个javascript对象创建的时候都会有一个与之关联的对象,该对象就是原型,创建的对象从原型中继承方法和属性,我们来看一个例子
function Demo(){
}
Demo.prototype.name = 'xx'
const demo = new Demo()
const demo1 = new Demo()
demo.name === demo1.name // true
demo和demo1都是Demo的实例,Demo.prototype指向实例对象的原型,也就是上述例子中的demo,demo1的原型
那么怎么关联实例和原型之间的关系呢?
proto
简单来说每一个对象都有一个私有属性__proto__指向原型 我们可以用例子来确定一下这个观念
Demo.prototype === demo.__proto__ // true
所以上述的图可以更新为
constructor
知道了实例和实例原型,构造函数和实例原型的关系,那么构造函数和实例原型之间存在什么样的关系呢? 实例原型有一个constructor属性指向构造函数,我们可以用一段代码验证一下
Demo === Demo.prototype.constructor // true
所以上图又可以更新为
那么构造函数有没有什么属性可以指向实例呢?
答案是没有,因为一个构造函数可以创建多个实例
原型链
之前我们也说过,原型是一个对象,对象都可以通过new Object()去创建,所以可以理解为实例原型就是继承自Object,写个例子验证一下
Demo.prototype.__proto__ === Object.prototype // true
所以可以把上图修改为
到了这一步,应该会想到,那么Object.prototype的原型又是什么呢?
Object.prototype.__proto__ // null
文章再开头就提到原型链的概念就是通过原型对象层层向上,直到null为止,所以上图就可以补充完成啦
上图中蓝色部分就是原型链
在网上看了一张原型关系的图,非常易于理解,贴在下方
instanceof
上面我们说了构造函数,原型和原型链的概念,接下来看看如何实现一个instanceof运算符 说一下实现的概念,一句话形容就是右边变量的原型在左边变量的原型链上即可
function myInstanceof(left, right) {
const rightProto = right.prototype
let leftProto = left.__proto__
while(leftProto !== null) {
if (leftProto === rightProto) {
return true
break
}
leftProto = leftProto.__proto__
}
return false
}
举个例子
function demo(){}
myInstanceof(demo, Object) // true
首先demo.__proto__等于Function.prototype,Function.prototype.__proto__等于Object.prototype,Object的原型就是Object.prototype所以返回true