一、 基本概念
我们知道在js中,原型链是实现继承关系的主要机制,而在实际编程过程中有两个与原型相关的属性,一个是prototype一个是__proto__,这两个属性有什么联系与区别呢?首先需要明确几个概念:
- 每一个对象都有一个__proto__属性,此属性本质是对象的一个内部的指针,指向了对象的构造函数的原型对象。在浏览器环境如Chrome及Firefox及node环境下都可以访问到这一属性,但因为这一属性是对象的内部指针,所以在标准中不推荐直接使用这一属性。
- 每个构造函数都有一个对应的原型对象,通过构造函数的prototype属性可以访问到这一原型对象。原型对象作为一个对象也有其__proto__属性。
二、详细探究prototype与__proto__
下面以代码和图片为例,详细解释一下创建一个构造函数及其实例后prototype和__proto__属性的区别,首先创建一个构造函数名为Fun并创建一个它的实例:
function Fun() {
}
var fn = new Fun();
那么此时实例fn的__proto__属性即一个内部指针即指向了其构造函数Fun的原型对象:
console.log(fn.__proto__ === Fn.prototype); // ture
同时我们想到,构造函数的原型对象本身也有__proto__,那么它的__proto__指向哪个对象呢?答案是默认情况下构造函数的原型对象的构造函数即为Object,Object本身也是一个构造函数,所以可以通过代码进行验证:
console.log(Fn.prototype.__proto__ === Object.prototype); // true
那么再往下深入,构造函数本质也是一个对象,它的__proto__指向哪个对象呢?通过上面的第一点可知它的__proto__指向了它的构造函数的原型对象。在js中所有函数对象的构造函数都是Function对象,它是js内部提供的一个对象,同时它也有自己的原型对象,通过代码来解释:
console.log(Fn.__proto__ === Function.prototype); // true
此外Function没有自己的构造函数,它是被自身所构造的,所以其__proto__指向了自己的原型对象:
console.log(Fn.__proto__ === Function.prototype); // true
同理,由我们创建的构造函数Fun的原型对象的__proto__指向Object的原型对象可知,Function的原型对象的__proto__也指向Object的原型对象:
console.log(Function.prototype.__proto__ === Object.prototype); // true
继续深入探究,刚刚几个对象的原型及__proto__属性都涉及到了Object对象,那么Object对象的__proto__指向了哪个对象呢?答案是因为Object对象本身也是一个构造函数,所以Object对象的__proto__指向了它的构造函数的原型对象,同时Object的构造函数也是Function,可以通过代码来验证:
console.log(Object.__proto__ === Function.prototype); // true
最后,Object的原型对象没有自己的构造函数,其__proto__指向为null:
console.log(Object.prototype.__proto__ === null); // true
因为关系比较复杂,可以结合图片来理解:

三、原型链与继承的实现
随后我们创建另一个类型SubFun,其继承了Fun,则它的原型对象的__proto__指向了Fun的原型对象,同时SubFun的原型对象也是Fun的一个实例对象。代码如下:
function SubFn() {
}
SubFn.prototype = new Fn();
console.log(SubFn.prototype.__proto__ === Fn.prototype); // true
实现继承关系后的关系图如下所示:

四、总结
通过以上可以得到几点总结:
- 所有的函数对象的构造函数都是Function对象,这一点从几个构造函数__proto__的指向可以得到验证。
- 自定义的未实现继承关系的构造函数的原型对象的构造函数都是Object,而且Object本身也是一个构造函数。实现了继承关系的构造函数的原型对象的__proto__指向其直接继承的构造函数的原型对象。
- 因为Object本身是也一个构造函数,也是一个函数对象,所以它的__proto__也指向Function的原型对象。
- Function的构造函数是自己,所以其__proto__指向为自身。