h
这幅图揭示了JS中原型继承的关系:
1. JS中对象在创建时,它的默认的原型属性为其构造函数的prototype属性。那构造函数的prototype属性又是从哪来的呢?往下看
2. JS中函数在定义时会自动的被添加一个prototype属性,该属性的值是一个对象,且该对象只有一个属性,该属性的值指回到该构造函数。即
1 //定义构造函数 2 function Foo() {} 3 4 Foo.prototype = { 5 constructor : <<reference to Foo>> 6 } 7 8 //创建对象 9 var obj = new Foo(); 10 11 //当我们访问对象的constructor属性时 12 //获得的值其实就是构造函数的prototype的constructor属性的值 13 obj.constructor === Foo.prototype.constructor //true
3. JS中函数也是对象,所以所有函数的原型指向的是函数的构造函数的prototype属性。函数的构造函数指的就是图中最下面的那个Function函数,它是JS中所有函数的构造函数(包括它自己)。从图中可以看到对象的的构造函数Object,其原型也是指向Function.prototype的。
4. 函数的prototype属性是一个对象,而对象都是有原型的,所以prototype的原型是构造函数Object的prototype属性。问题来了,Object.prototype也是一个对象,那它的原型又是什么?跟前面一样也是Object.prototype吗,那这不成了死循环了吗?而且我们知道在查找对象的属性时会沿着原型链进行查找,如果前面原型的继承出现死循环,那对象属性的查找岂不会导致死循环?所以,Object.prototype虽然是个对象,但是其原型指向的是null(如图所示)。