详解原型链中的prototype和 __proto__

栏目: JavaScript · 发布时间: 6年前

内容简介:本文主要是彻底讲明白如果你之前了解过 java 这种面向对象编程的语言,你应该会熟悉类的概念,在面向对象编程的语言中,首先设计出类(class),然后再生成类的实例(实例化成对象)。 但是也可以参考阮一峰老师的:

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

为什么会创造出 prototype和__proto__

javascript 没有类的概念

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

也可以参考阮一峰老师的: Javascript继承机制的设计思想

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 类型衍生出来的。

代码如下:

详解原型链中的prototype和 __proto__

Function 和 Object

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

Function 和 Object 的区别

  • Function 可以被执行
  • Function 可以当做 Object 的构造函数,比如当我们使用 new操作符后面跟着一个 Function时,这个 Function会被当成构造函数返回一个对象。 代码如下:
    详解原型链中的prototype和 __proto__

从上图我们可以看出,构造函数本身是一个 function ,而构造函数返回的实例其实是一个object

  • Function 有 prototype 属性,而 Object 没有. 代码如下:
    详解原型链中的prototype和 __proto__

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

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

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

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

那么,javascript 究竟是通过什么来确定继承关系的呢? 答案是 proro

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

代码如下:

详解原型链中的prototype和 __proto__

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

示例代码:

详解原型链中的prototype和 __proto__

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

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

new 操作到底做了什么

详解原型链中的prototype和 __proto__

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

详解原型链中的prototype和 __proto__

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

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

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

总结

最后,我们用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__的对象


以上所述就是小编给大家介绍的《详解原型链中的prototype和 __proto__》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java语言程序设计

Java语言程序设计

(美) Y. Daniel Liang / 李娜 / 机械工业出版社 / 2011-6 / 79.00元

本书是Java语言的经典教材,畅销多年不衰。本书全面整合了Java的特性,采用“先讲基础”的教学方式,循序渐进地介绍了程序设计基础、面向对象程序设计、GUI程序设计等。另外,本书还全面且深入地覆盖了一些高级主题,包括算法和数据结构、并发、网络、国际化、高级GUI、数据库和Web程序设计等。 本书中文版由《Java语言程序设计 基础篇》和《Java语言程序设计 进阶篇》组成。基础篇对应原书的第......一起来看看 《Java语言程序设计》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具