之前在学习Javascript的时候对Js的原型链总是有所不解,就是绕的有点晕,对于没搞明白的事情,我总是要想办法去整明白的,今天在温习的时候,看了一篇文章,终于让我理解了Js的原型链。
一般在讲解的时候都拿下面这种图来说明原型链。
其中有几个名词需要搞明白,构造函数、实例对象、原型对象、prototype
属性、constructor
属性、__proto__
属性;只有把这些名词整明白了才能画出整张原型链图出来。
解释名词之前,需要特别的清楚一点,在Javascript语言里,一切都是对象
,这一句特别关键。其中__proto__
是隐式属性,每个对象都有这个属性,一开始我是忽略了这个说明,导致在理解原型链的时候总有疑惑。
借用下面的代码来说明一下原型链
function Person() {
this.name = 'aaa';
this.age = '69';
this.eat = function () {
console.log(this.name +' is eating!')
}
}
Person.prototype.smell = function () {
console.log("smell");
};
var person1 = new Person();
复制代码
构造函数function Person()
,实例对象person1
,原型对象Person.prototype
根据上图可知:
person1.__proto__ == Person.prototype
person1.__proto__.constructor == Person.prototype.constructor
person1.__proto__.constructor == Person
可知
Person.prototype.constructor == Person
复制代码
既然一切都是对象,对象都有__proto__
属性,那么Person
和Person.prototype
也是有的了,那么他们的__proto__
由指向哪里呢?
为了理解这个,也需要事先了解2个对象,Function对象、Object对象。把这两个理解了,原型链也就很容易画出来了。
var obj = new Object();
复制代码
函数和对象,函数也是对象,在原型链的顶端,应该是这样的,一端是Object
构造函数,一端是Object.prototype
原型对象,他们的关系也和上面的图示是一样的。咱们要解决最终的__proto__
的指向,就是看Object.__proto__
和Object.prototype.__proto__
的指向了,咱们还是借用网友的图片来说明。
从上图可知,Object.__proto__
指向Function.prototype
,那Function.prototype.__proto__
又指向哪里呢,其实Function.prototype.__proto__
指向了Object.prototype
,绕来绕去,最终的__proto__
都指向了Object.prototype
了,而Object.prototype.__proto__
指向null,真是一切皆空啊,哈哈,有点道生一,一生二,二生三,三生万物的感觉了。
上面还有一个比较有趣的现象,Function.__proto__
指向是Function.prototype
。
总结
通过以上的学习可以得知__proto__
指向的一定是原型对象,最终指向null,Object.prototype
是原型对象最后的大Boss。
Javascript的方法是沿着__proto__
进行查找的,所以一般方法的查找过程是这样的,
1、首先通过实例对象自身;
2、接着是找到对象原型;
3、接着就是往上追溯,直到Object.prototype
,如果这个也没有则查找失败。
补:
再来学习一下instanceof这个运算符,下面这个解释最好理解了Instanceof的判断队则是:沿着A的__proto__这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。
所以下面的结果都是true
Object instanceof Function // true
Function instanceof Object //true
Function instanceof Function //true
复制代码
参考文章:
1、 深入理解javascript原型和闭包(4)——隐式原型
2、深入理解javascript原型和闭包(5)——instanceof