# 困扰我很久的问题:原型链到底是啥啊!

# 首先我们先来聊聊什么是原型什么是原型链

首先我们需要有一个构造函数

function Car() {
}
var car = new Car();
car.name = 'Benz';
console.log(car.name) // Benz

Car 就是一个构造函数 那么 car就是用new方法创建的 Car的一个实例

# 那么prototype是什么?

function Car() {
}
var car = new Car();
//这时我们能在Car 上找到属性prototype
// 但是car 却没有 只有__proto__ 这是什么?  稍后再讲

那么我们武断的得出结论 只有function 才有prototype属性 那么prototype可以做什么?我们不妨进行以下实验

function Car() {
}
var car = new Car();
var car2 = new Car()
Car.prototype.name = "Benz"
car.name = "BMW"
console.log(car.name)// BMW
console.log(car2.name)//Benz
delete car.name
console.log(car.name)//Benz

发现规律了嘛?当实例没有这个属性的时候,会默认使用这个实例构造函数的 prototype 上的属性
那么如果构造函数的 prototype 也没有呢?那就Car.prototype.prototype直到找到最顶层
如果都没有 那就是 undefined

#__proto__又是啥

说到这里 就有意思了 每一个对象 或者说实例 都有__proto__,这个属性会指向构造函数的原型

function Car() {
}
var car = new Car();
Car.prototype.name = "benz"
car.__proto__.name  = "BMW"
console.log(Car.prototype.name)//BMW

代码写到这,我就猜测 car.__proto__ 就等价于 Car.prototype

让我武断的给他俩画个等于号吧~

function Car() {
}
var car = new Car();
、
console.log(Car.prototype == car.__proto__ )//true

诶!有意思的地方来了 既然实例可以找到原型的属性 那原型能找到"实例"嘛?

当然可以

# constructor 是什么神奇东东

上面的实例打了双引号,因为一个构造函数有多个实例 构造函数并不能反过来找实例 但是构造函数的原型可以

我把构造函数看做圆形特殊的"实例"

function Car() {
}
console.log(Car === Car.prototype.constructor); // true

那我们不难得出以下结论

Car == Car.prototype.constructor   
Car.prototype == car.__proto__  
car.__proto__.constructor == Car  

通过这个我们就可以用car 找到他的构造函数啦~