一、什么是原型链?
简单回顾下构造函数,原型和实例的关系:
每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针.
然鹅,在js对象里有这么一个规则:
如果试图引用对象(实例instance)的某个属性,会首先在对象内部寻找该属性,直至找不到,然后才在该对象的原型(instance.prototype)里去找这个属性.
少废话,先来看个例子:
function Fun1 () {
this.win = "skt"
}
Fun1.prototype.getVal = function () {
return this.win
}
function Fun2 () {
this.other_win = "rng"
}
Fun2.prototype = new Fun1 ()
Fun2.prototype.getOtherVal = function () {
return this.other_win
}
let instance = new Fun2()
console.log(instance.getVal()) //skt
在上述例子中,有一个很有意思的操作,我们让原型对象指向了另一个类型的实例,即: constructor1.property = instance2
那么他是怎么找到instance.getVal()的?这中间又发生了什么?
1).首先会在instance1内部属性中找一遍;
2).接着会在instance1.proto(constructor1.prototype)中找一遍,而constructor1.prototype 实际上是instance2, 也就是说在instance2中寻找该属性;
3).如果instance2中还是没有,此时程序不会灰心,它会继续在instance2.proto(constructor2.prototype)中寻找…直至Object的原型对象
搜索轨迹: instance1--> instance2 --> constructor2.prototype…-->Object.prototype
这种搜索的轨迹,形似一条长链, 又因prototype在这个游戏规则中充当链接的作用,于是我们把这种实例与原型的链条称作 原型链
二、prototype 和 proto 都是个啥?
1.prototype是函数才有的属性
let fun = function () {}
console.log(fun.prototype) // object
console.log(fun.__proto__) // function
2.__proto__是对象具有的属性,但__proto__不是一个规范的属性,对应的标准属性是 [[Prototype]]
let obj = {}
console.log(obj.prototype) // underfined
console.log(obj.__proto__) // object
我们可以把__proto__理解为构造器的原型,大多数情况下 proto === constructor.prototype ( Object.create()除外 )
三、new又是个什么鬼?
我们都知道new是一个实例化的过程,那么他是怎么实例化的?下面我们来看一个简单的例子:
function Fun() {
this.team = "rng"
}
let f = new Fun()
console.log(f.team) // rng
上述代码中,我们通过new命令实例化了一个叫Fun的函数并赋值给f,这个新生成的实例对象f从构造函数Fun中得到了team属性,其实构造函数内部的this,就代表了新生成的实例对象,所以我们打印f.team的值就取到了rng这个值
这又是哪门子原理?答案如下?
1.创建一个空对象&#