今天是系列第三篇,主要讲一下原型链相关的问题。
先来看一个例子:
Object.prototype.getA = function(){
console.log('我是对象A')
}
Function.prototype.getB = function(){
console.log('我是函数B')
}
function Person(name){
this.name = name
}
var p = new Person('Bob')
Person.getA() // 我是对象A
Person.getB() // 我是函数B
p.getA() // 我是对象A
p.getB() // p.getB is not a function
要解决这个问题,我们需要先了解原型链创建的过程。
原型链的创建过程
我从jsliang文章中引过来的一张图,比较有意思,有兴趣的可以看一下:
结合上面这张图,我们需要记住几个关键结论。
1、Function.__proto__ === Function.prototype
2、Object.prototype.__proto__ === null
3、Function.__proto__.__proto__ = Object.prototype
看了上面的图还是不知道原型链是什么?我们来梳理一下。
什么是原型链
先给原型链下个定义:从当前对象出发,沿着__proto__属性向上找构造函数的prototype,一直找到null为止结束,在查找属性的过程中形成的链叫做原型链。看个例子:
var obj = {
name: 'Bob',
getName: function(){
console.log(111)
}
}
var cloneObj = Object.create(obj)
cloneObj.getName() // 111
我们执行一下上述代码,输出了111.可以看到通过Object.create(obj)会创建一个原型为obj的一个空对象,我们在执行cloneObj.getName()的时候,会先去找cloneObj对象中是否有getName这个方法,最后发现没有,就会去它的原型链上找,然后在它的原型链上找到了对应的方法,然后执行输出。
接下来,我们还要记住实例和原型之间的关系,来帮助我们更好的解决这个题目。
实例和原型的关系
上面我们说到了原型链是从当前对象出发向上找构造函数原型的过程,那么存在这样一个关系:
new Fun().__proto__ === Fun.prototype
即构造函数实例的__proto__属性会指向构造函数的原型。
解题过程
有了上面的知识点可以解决开头的那个问题了。
1、先看Person.getA(),首先我们去看Person是不是有getA方法,发现没有然后去上层构造函数找;Person的上层函数是Function,那就是去看Function.prototype上是否有getA方法,发现没有,再继续往上走去找Object.prototype是否有getA方法,找到了就输出“我是对象A”.
2、再看Person.getB(),首先我们去看Person是不是有getB方法,发现没有然后去上层构造函数找;Person的上层函数是Function,那就是去看Function.prototype上是否有getB方法,发现有输出了“我是函数B”。
3、再看p.getA(),跟上面同样的办法,找本身对象有没有getA方法,发现没有向上找Object.prototype上的getA,找到了输出“我是对象A”.
4、最后看p.getB(),跟上面同样的办法,找本身对象有没有getB方法,发现没有向上找Object.prototype上的getB,没有找到继续找上层Object.prototype.__proto__,发现是null,停止了,没有找到该属性。所以最后执行的时候报错,相当于是undefined()的执行效果。
所以结果是
我是对象A
我是函数B
我是对象A
p.getB is not a function
知识点总结
- 原型链是什么?
从当前对象出发,通过__proto__属性向上找构造函数的prototype属性,一直找到null而结束,在查找过程中形成的链叫做原型链
- 对象查找某个属性和方法的时候,会先查找当前对象中是否存在该属性或者方法,如果没有,则会去他的原型链上查找。
- 原型链的上几个重要关系,记不住可以看上面那张图。
Function.__proto__ == Function.prototype
Object.prototype.__proto__ === null
Function.__proto__.__proto__ === Object.prototype
- 当前构造函数的实例的__proto__属性指向构造函数的prototype
拓展
与原型链相关的知识点还有继承,new关键字做了什么,this指向,instanceof的实现原理等。篇幅有限,后期再更新。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。