Prototype Chain
要了解原型链,首先要知道prototype和__proto__
prototype
实例都有一个构造函数属性(constructor)指向构造函数,通过构造函数创建的对象拥有构造函数内部定义的属性和方法
function Test(name, age) {
this.name = name
this.age = age
}
Test.prototype.say = function () {
console.log('say')
}
let obj = new Test('xiaoming', 20)
let obj2 = new Test('xiaohong', 21)
console.log(obj.constructor === Test) // true
console.log(obj2.constructor === Test) // true
console.log(obj.constructor === obj2.constructor) // true在js中,每一个对象(函数也是对象)都有一个特殊的属性叫原型(prototype),它指向另一个对象,这个对象(Test.prototype)被称为原型对象,原型对象是用来共享属性和方法的
function Test(name, age) {
this.name = name
this.age = age
}
Test.prototype.say = function () {
console.log('我能说话')
}
var obj3 = new Test('Jack', 26)
var obj4 = new Test('Rose', 25)
obj3.say() // 我能说话
obj4.say() // 我能说话
console.log(obj3.say === obj4.say) // true__proto__
每个对象都有一个__proto__属性,被称为隐式原型
console.log(obj3.__proto__ === Test.prototype) // true每个js对象的__proto__,它指向创建它的构造函数的原型对象
__proto__的意义在于为原型链查找提供方向,原型链查找靠的是__proto__,而不是prototype

prototype chain
Test.prototype当然也存在属性__proto__,那么Test.prototype.__proto__是谁呢
console.log(Test.prototype.__proto__ === Object.prototype) // true所有的对象,包括构造函数的原型对象,最终都是继承自Object.prototype,这是js原型链的顶点
Object.prototype作为原型链的顶端,因此,Object.prototype.__proto__指向null,表示原型链的终点
console.log(Object.prototype.__proto__ === null) // true
每一个对象都有一个原型(prototype)指向另一个对象,而这个对象又存在属性(__proto__)另一个对象
当我们访问一个对象的属性时,会先在自己的属性中查找,没找到就会沿着__proto__一路向上找。最终形成一个链式结构,称为原型链
进阶
原型链机制
还记得__proto__存在的意义时为原型链查找提供方向 
Function的原型
Function.prototype === Function.__proto__
按照刚才的结论,函数对象的__proto__应该指向Function.prototype(即function.prototype.__proto__ === function.prototype),但是自己指向自己没有意义。别忘记Object.prototype才是原型链的终点,指向Object.prototype能保证原型链存在终点,所以Function.prototype.__proto__ === Object.prototype

如果再深究一点,Object也是函数对象,Object.__proto__ 也会指向Function.prototype
构造函数Test也有constructor属性,这个属性指向创建该函数的构造函数;如果自己没有构造函数,会指向Function
原型链就成了这样: 
在构造函数Test上访问Object.prototype中的属性时,其实是顺着Test.__proto__从Function去访问的
function Test(name, age){
this.name = name
this.age = age
}
var obj = new Test('Jack', 26)
Object.prototype.price = 2000
Function.prototype.price = 300
Test.price // 300若Function.prototype上没有price,才会往上找到Object.prototype