1  | function Person() {  | 
Person 就是一个构造函数,new 来创建一个实例对象 person
Prototype
prototype是*只有 函数 *才会有的一种属性
1  | function Person() {  | 
函数的 prototype 属性指向一个对象,这个对象就是 调用这个构造函数创建的实例的原型,也就是 person1 和 person2 的原型

__proto__
每个对象都有一个 __proto__ 属性,指向它的原型,也就是其构造函数的prototype属性

constructor
每个原型对象都有一个指向其构造函数的 constructor 属性
1  | Person.prototype.constructor === Person  | 

构造函数、实例 和 原型对象的关系:
1  | Person.prototype === person.__proto__  | 
原型链
javascript 中继承的原理就是原型链
1  | function Person () {  | 
当读取实例的属性时,javascript 首先会在实例上查找有没有这个属性,如果在实例身上没有找到,那么就会上翻一级,在 person.__proto__ 上查找是否有对应的属性,上面的例子就是这样的一种情况
但是如果在实例的原型对象上还是没有找到对应的属性呢?这就涉及到了原型链的知识,如果在实例的原型对象上还是没有找到对应的属性,javascript 就会顺着原型链继续查找
原型链,说白了就是
1  | instance.__proto__.__proto__.xxxxx = Constructor.prototype  | 
就是这样的一个链式结构,javascript会在这个原型链的原型对象上查找对应属性,直到找到了对应属性,或到了null
这个原型链是一定会有终点的,当javascript到达我们定义的继承链的最上层时,这个原型对象就会被看做一个普通的object,它是可以通过 new Object 来创建的,也就是说
1  | var object = new Object();  | 
Person.prototype 其实就是这样的一个对象,所以说,Person.prototype.__proto__,是指向 Object.prototype 的,而 Object.prototype.__proto__,就是 null
javascript原生对象的原型链
1  | Array.prototype.__proto__ === Object.prototype  | 
构造函数作为实例,其原型对象
1  | // 构造函数的原型对象:  | 
我们之前讲过,所有对象都有 __proto__ 属性,那么 函数对象自然也是有 __proto__ 属性的,每个函数,都可以看做是 new Function() 构建出来的,所以
1  | Person.__proto__ === Function.prototype // true  | 
一个比较特殊的例子
1  | Function.__proto__ === Function.prototype  | 
可以理解为:就是先有的Function,然后实现上把原型指向了Function.prototype,但是我们不能倒过来推测因为Function.proto === Function.prototype,所以Function调用了自己生成了自己。一种内建规则,不必深究
Object.prototype 并不是一个正统的对象,因为它的__proto__ 为 null,可以说,对象都是实例,而实例不一定都是对象
【题外话】Function对象,所有的函数都是继承自 Function 对象,我们平时使用的 bind apply call 这些函数,都是在Function 的 prototype 上定义的属性—— MDN-Function
总结

