详解原型链中的prototype和 __proto__

前言

本文主要是完全讲明白prototype和__proto__ 是干吗的,相信不少同窗也跟我同样,傻傻的分不清楚二者应该如何使用?、在原型链中到底起到什么做用?、 在继承中起到什么做用?、javascript为何会设计出这两个属性?等一系列问题,网上查遍许多资料,看的也是云里雾里一头雾水,接下来,本文就通俗易懂的来说解以上问题,也当作本身的学习笔记。javascript

为何会创造出 prototype和__proto__

javascript 没有类的概念

若是你以前了解过 java 这种面向对象编程的语言,你应该会熟悉类的概念,在面向对象编程的语言中,首先设计出类(class),而后再生成类的实例(实例化成对象)。 可是 在 javascript 语言中,并无类的概念,全部的数据类型都是对象(object) ,这并无任何问题,不是全部的编程语言都必须向 java 同样依赖类的概念,C 语言就没有类的概念,同样活的很好。可是咱们不得不认可,类是思想会给项目工程问题带来不少方便。若是想构建一个大型项目,那必然会涉及到继承,继承问题,就须要经过类来实现,可是在 javascript 中并无类的概念,那应该怎么办呢,咱们能够模仿类,因此prototype和__proto__ 就衍生出来了。html

也能够参考阮一峰老师的:Javascript继承机制的设计思想java

javascript 中的数据类型

在讲解prototype和__proto__以前,咱们首先来说解一下 javascript 中的数据类型。为何要先讲下数据类型呢,由于prototype和__proto__用到了Function 和 Object 两种数据类型。 javascript 数据类型分为两种:编程

  • 基本数据类型:String Number Boolean Null undefined
  • 引用数据类型:Array Object Date Function RegExp 等

咱们能够用 typeof 来判断一个变量的数据类型,5种基本数据类型均可以用 typeof 判断出来(Null为 object), 而引用数据类型只能判断出 object 和 function 两种类型,也就是说,引用类型其实分两种 ObjectFunction ,其余的类型都是 Object 类型衍生出来的。编程语言

代码以下: ide

Function 和 Object

经过上面的讲解,接下来咱们的重点要放在 Function 和 Object 两个类型上。函数

Function 和 Object 的区别
  • Function 能够被执行
  • Function 能够当作 Object 的构造函数,好比当咱们使用 new操做符后面跟着一个 Function时,这个 Function会被当成构造函数返回一个对象。 代码以下:

从上图咱们能够看出,构造函数自己是一个 function ,而构造函数返回的实例实际上是一个object学习

  • 构造函数function 有 prototype 属性,而 实例 object 没有 prototype 属性. 代码以下:

明确了 Function 与 Object 的关系后,咱们接下来说解在继承中prototype和__proto__起到了什么做用。ui

在继承中prototype和__proto__起到了什么做用

在相似 java 这种语言中,继承的概念是经过类和类之间实现的,但 javascript 根本没有类,都是对象,因此,在 javascript中,继承的概念是经过对象和对象之间实现的。this

在考虑 javascript 继承的时候,范围只限于引用数据类型,虽然引用数据类型分为 Function 和 Object 两种,但在继承问题上,不须要区分 Function 和 Object,只须要统一当作对象便可。

那么,javascript 到底是经过什么来肯定继承关系的呢? 答案是 proro

__proto__和prototype 不一样,prototype 只在 Function 中有,而__proto__则在Function和Object中都有。

代码以下:

简单总结javascript继承的本质: 一个对象 A的__proto__属性指向的那个对象B,B就是 A 的原型对象(或者叫父对象),对象 A 可使用对象 B 中的属性和方法,同时也可使用对象 B 的 原型对象C 上的属性和方法,以此递归,就是所谓的原型链

示例代码:

以上代码实现了 javascript 最简单的继承,彷佛没什么,一个__proto__就实现了继承问题。那还要 prototype 作什么呢?prototype在继承中又起什么做用呢,其实 prototype 真正起做用的是把 Function 当作构造函数使用的时候,由于__proto__ 并非官方标准定义的属性,因此借助 prototype属性来模仿类和类之间的继承模式。

接下来重点分析用 Function类型构造对象过程,当你知道使用 new 操做符都作了什么的时候,你就很清楚 prototype 的做用了。

new 操做到底作了什么

经过上面的分析,咱们知道 p 是 object 的类型,Parent 是 Function 类型。 在 java中,若是你这么写,那么 Parent 应该是一个类(class),可是 javascript 中并无类,可是咱们又很想借鉴这种语法形式,应该怎么办呢,这个任务只能交给 Function。 看下完整代码:

上面这种写法,就是经典的构建构造函数,可是 new到底都干了啥呢?

  • 第一步:Parent 被执行。当使用 new关键字时,Parent 函数会在 p 的做用域下被执行,因此这里的 this 就是实例p,这样,name,age,hobby三个属性才会被当作 p 的属性被建立,
  • 第二步:将 p.__proto__指向 Parent.prototype,这才是构造函数的精髓所在,因此,p 就继承了 Parent.prototype中的(以及其原型链上的)属性和方法。验证以下:

这样,一个鲜活的实例就被建立出来了。

总结

最后,咱们用Stack Overflow上关于这个问题得票最多答案做为总结,他解释的很是简单

下面是答案:

__proto__is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__when you create an object with new

翻译一下:

__proto__是真正用来查找原型链去获取方法的对象。

prototype是在用new建立对象时用来构建__proto__的对象

相关文章
相关标签/搜索