灵魂拷问
你是怎么理解原型及原型链的?
回答
现在看图说话,我们可以把prototype和__proto__分别称为显示原型和隐示原型属性,构造函数会有一个显示原型属性,实例会有隐示原型属性,实例的原因会有一个constructor属性,他们的关系如图上部分所示构成一个三角关系.即构造函数生成实例person有一个__proto__隐示原型属性指向实例原型Person.prototype,而Person.prototype有一个construtor指向构造函数,构造函数Person有一个显示原型prototye属性指向实例原型.
再往下看,实例原型Person.prototype也有一个__proto__隐示原型属性,这时它会指向父级的构造函数的原型实例,就像person的__proto__隐示原型属性指向Person.prototype,而Person.prototype隐示原型指向Object.protoype,然后Object.protoype的隐示原型的指向最顶级就是null了,这样相当在查找某个方法和属性时,找不到会沿着__proto__往上找直到null,这样就构成了一个链条.
所以得出这样的结论:
console.log(Person === Person.prototype.constructor); // true
console.log(person.__proto__ === Person.prototype); // true
console.log(Person.prototype.constructor == Person) // true
扩展
当我们new一个对象的时候发生了什么?
- 创建一个空对象 obj = {}
- 绑定原型,
obj.__proto__ = Person.prototype - 调用 Person() 函数,并把空对象 obj 当做 this 传入,即 Person.call(obj)
- 如果 Person() 函数执行完自己 return 一个 object 类型,那么返回此变量,否则返回 this
拿上面的Person来说,实例person 时通过 new Person()得出来的,其实new的过程有一步就是绑定新对象原型即这个对象的__proto__指向Person.protorype,可以联想到上面所说的关系.