之前在学习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