prototype与__prototype__与原型链

来源:互联网 发布:艾美依航空制造 知乎 编辑:程序博客网 时间:2024/06/09 20:15

一、 基本概念

我们知道在js中,原型链是实现继承关系的主要机制,而在实际编程过程中有两个与原型相关的属性,一个是prototype一个是__proto__,这两个属性有什么联系与区别呢?首先需要明确几个概念:

  1. 每一个对象都有一个__proto__属性,此属性本质是对象的一个内部的指针,指向了对象的构造函数原型对象。在浏览器环境如Chrome及Firefox及node环境下都可以访问到这一属性,但因为这一属性是对象的内部指针,所以在标准中不推荐直接使用这一属性。
  2. 每个构造函数都有一个对应的原型对象,通过构造函数的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

实现继承关系后的关系图如下所示:
对象关系2

四、总结

通过以上可以得到几点总结:

  1. 所有的函数对象的构造函数都是Function对象,这一点从几个构造函数__proto__的指向可以得到验证。
  2. 自定义的未实现继承关系的构造函数的原型对象的构造函数都是Object,而且Object本身也是一个构造函数实现了继承关系的构造函数的原型对象的__proto__指向其直接继承的构造函数的原型对象。
  3. 因为Object本身是也一个构造函数,也是一个函数对象,所以它的__proto__也指向Function的原型对象。
  4. Function的构造函数是自己,所以其__proto__指向为自身。
原创粉丝点击