在 JavaScript 中创建对象使用 new 关键字,而后跟着的是构造函数。在 JavaScript 中没有类的概念,所以对象的构造函数就是单纯只是个函数(function)。

单纯使用构造函数的方式来创建对象,有一个问题,那就是无法共享属性和方法,当两个对象都有一个同名的相同的方法时,方法会在每个实例上重新创建,这无疑是一种浪费。

创建函数时,函数都会有一个原型(prototype)属性,该属性是一个指针,指向一个对象。而这个对象的用途就是包含那些共享的属性和方法。prototype 就是通过调用构造函数而创建的对象实例的原型对象。

构造函数模式用于定义实例的属性,而原型模式用于定义方法和共享的属性。这里有一点继承的味道,如果把 prototype 当作是父类的话,那么构造函数创建的对象就是原型对象的子类。

每个构造函数都有一个原型对象(创建函数时会有一个原型属性),原型对象中包含一个指向构造函数的指针(constructor 指向构造函数)而实例对象中包含一个指向原型对象的内部指针(实例对象中的 [[Prototype]] 它不能被显式的访问)。

在 ECMA-262 中定义此指针为[[Prototype]],并不能被显式的访问到,而在 FirefoxSafari 和 Chrome 中每个对象上有一个proto属性。

那么如果这里面的原型对象是另一个实例对象的话,就可以使得实例与实例之间产生了关联,并且由于原型对象是另一个实例对象的关系,此时这个作为原型对象的实例对象的属性和方法变成了原型对象对应的构造函数创建的实例的“父类”。

这样层层递进,构成实例和原型间的链条,就让实例之间产生了关联,那么就实现了继承。这个就是原型链的基本概念。