我们创造的每一个函数都有一个prototype(原型)属性。这个属性是一个指针,指向原型对 象。在默认情况下,所有的原型对象都会有一个constructor(构造函数)属性,这个属性包含一个指向prototype属相所在的指针。当调用构造函数创建一个新实例之后,该实例内部将包含一个指针(内部属性),指向构造函数的原型对象。
构造函数创建对象
一:什么是原型?每一个javascrip对象(除null)在创建时都会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型继承。
让我们用一张图表示构造函数和实例原型之间的关系:

二:每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__(内部属性),这个属性会指向该对象的原型。
function Person() {
}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true可以有以下关系图:

三:constructor,每个原型都有一个 constructor 属性指向关联的构造函数。
可以通过代码进行验证:
function Person() {
}
console.log(Person === Person.prototype.constructor); // true所以再更新关系图:

综上所述可以得到:(代码表示)
function Person() {
}
var person = new Person();
console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
// 顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true在浏览器中可以看出:

实例与原型
当读取实例中是属性时,如果找不到,就会去原型中查找,如果找不到就会去找原型的原型,一直找到最顶层为止。
function person(){
}
person.prototype.name = "kevin";
var person1 = new person();
person1.name = "disy";
console.log(person1.name);
在浏览器中操作得到结果:

可以看出。删除实例中的name后,向上查找到了原型中的name属性。
原型的原型
原型是一个对象,我们可以用最原始的方式来创建它:
var obj = new Object();
obj.name = 'Kevin'
console.log(obj.name) // Kevin其实原型对象就是通过 Object 构造函数生成的,结合之前所讲,实例的 __proto__ 指向构造函数的 prototype ,所以我们再更新下关系图:

原型链
文章的开头就讲了:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针 .
假如我们让原型对象等于另一个类型的实例。此时,原型对象将包含一个指向另一个原型的指针。假如,另一个原型又是另一个类型的实例。层层递进,就构成了实例与原型的链条。
注意:Object.prototype的原型呢?
console.log(Object.prototype.__proto__ === null) // true引用阮一峰老师的 《undefined与null的区别》 就是:
null 表示“没有对象”,即该处不应该有值。
所以 Object.prototype.__proto__ 的值为 null 跟 Object.prototype 没有原型,其实表达了一个意思。
所以查找属性的时候查到 Object.prototype 就可以停止查找了。
最后一张图的更新:

图中的相互的链状结构的关系组成原型链,也就是蓝色部分。
参考: 《JavaScript高级程序设计》
冴羽的博客