原型

前言

继承是面向对象编程中相当重要的一个概念,它对帮助代码复用起到了很大的作用。

正文

Brendan Eich在创建JavaScript时,没有选择当时最流行的类继承机制,而是借鉴Self,用到了基于原型(prototype)的继承机制,这导致了JavaScript在继承机制方面与Java、C++等基于类继承机制的语言有着显著的区别。

其具体在于—C++的多重继承、Java的继承和接口实现中都包含""的概念,它们倾向于在创建对象之前[1]已经规定了对象需要继承的类和实现的接口,并且使用类与类之间的继承方式

而在JavaScript中没有""的概念,在对象之后所继承的对象也是可以发生动态变化的,并且使用的是对象与对象之间的继承方式

如果将JavaScript中由string,number,bigint,boolean,null,undefined,symbol组成的基础类型与其对应的值都按下不表,余下的引用类型与其对应的值将都存在着__proto__[2]属性,指向继承的原型对象[3]

与__proto__存在于每个对象中不同,prototype属性只存在于函数中,在默认的的情况下所有对象的__proto__属性的值与其构造函数下的prototype属性的值是一致的。

let obj = new Object();
obj.constructor === Object;//true
//obj的__proto__属性的值与obj的构造函数的prototype属性的值指向同一块堆内存
obj.__proto__ === obj.constructor.prototype;//true
obj.__proto__ === Object.prototype;//true

所有函数的构造函数都指向Function:

Object.constructor === Function;//true
//Object的__proto__属性的值与Object的构造函数的prototype属性的值指向同一块堆内存
Object.__proto__ === Object.constructor.prototype;//true
Object.__proto__ === Function.prototype;//true Function.constructor === Function;//true
//Function的__proto__属性的值与Function的构造函数的prototype属性的值指向同一块堆内存
Function.__proto__ === Function.constructor.prototype;//true
Function.__proto__ === Function.prototype;//true

Function的prototype属性的原型指向Object.prototype:

Object.prototype === Function.prototype.__proto__;//true

不单单是 Function 的prototype属性的原型指向 Object.prototype ,几乎所有的函数[4]的prototype属性的原型指向 Object.prototype ,从V8的测试代码中可见一斑:



最后,位于原型顶点的是Object.prototype.__proto__,它指向 null:

Object.prototype.__proto__ === null;//true
Object.prototype.constructor === Object;//true

根据以上逻辑画的原型指向图:



为了加深理解,我将再定义一个构造函数:

function Person(){

}
Person.constructor === Function;//true
Person.__proto__ === Person.constructor.prototype;//true
Person.__proto__ === Function.prototype;//true



通过新定义的构造函数创建对象:

let person = new Person();
person.constructor === Person;//true
person.__proto__ === person.constructor.prototype;//true
person.__proto__ === Person.prototype;//true



根据以上逻辑画的最终的原型指向图:

结尾

了解JavaScript中基于原型(prototype)的继承机制的重点在于捋清楚Object与Function的__proto__、constructor、prototype属性的指向关系,再进一步了解Object和Function各自对应的值以及通过Function对应的值创建出来的对象的__proto__、constructor、prototype属性的指向关系,就大功告成了。

听起来可能有一点点绕,最好是动手画一下图,以后忘记的时候看一下自己画的图就又想起来了。

最后,本人才疏学浅,如有错误之处,还望各位不理赐教。


  1. 这里的措辞最初为程序运行之前,后联想到hotswap,特意改为对象创建后。

  2. 虽然__proto__已经被不推荐使用,但是为了更直观,我在此文中获取对象原型的方法都将通过对象的__proto__属性,还望悉知。

  3. Object.prototype继承的原型指向null。

  4. bind、apply和call没有prototype属性。

深入了解JavaScript中基于原型(prototype)的继承机制的更多相关文章

  1. JavaScript中的原型prototype和__proto__的区别及原型链概念

    问题 初学js的同学,总是搞不清楚js中的原型是什么东西,看着控制台打印出来的一串串__proto__,迷惑不已. 例如我定义一个Person,创建一个实例p,并打印实例. function Pers ...

  2. JavaScript中的原型链和继承

    理解原型链 在 JavaScript 的世界中,函数是一等公民. 上面这句话在很多地方都看到过.用我自己的话来理解就是:函数既当爹又当妈."当爹"是因为我们用函数去处理各种&quo ...

  3. JavaScript之基于原型链的继承

    本文介绍下js的OOP中的继承. 上图的要点为:Foo函数在创建时会自动生成内置属性prototype,而typeof Foo.prototype是object类型的. 上图的要点为:Foo.prot ...

  4. 【转】JavaScript中的原型和继承

    请在此暂时忘记之前学到的面向对象的一切知识.这里只需要考虑赛车的情况.是的,就是赛车. 最近我正在观看 24 Hours of Le Mans ,这是法国流行的一项赛事.最快的车被称为 Le Mans ...

  5. 理解JavaScript中的原型继承(2)

    两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...

  6. javascript中的原型继承

    在Javascript面向对象编程中,原型继承不仅是一个重点也是一个不容易掌握的点.在本文中,我们将对Javascript中的原型继承进行一些探索. 基本形式 我们先来看下面一段代码: <cod ...

  7. 图解JavaScript中的原型链

    转自:http://www.jianshu.com/p/a81692ad5b5d typeof obj 和 obj instanceof Type 在JavaScript中,我们经常用typeof o ...

  8. 前端知识体系:JavaScript基础-原型和原型链-理解原型设计模式以及 JavaScript中的原型规则

    理解原型设计模式以及 JavaScript中的原型规则(原文地址) 1.原型对象:我们创建的每一个函数(JavaScript中函数也是一个对象)都有一个原型属性 prototype,原型属性实质上是一 ...

  9. JavaScript中的原型、原型链、原型模式

    今天,咱来聊聊JavaScript中的原型跟原型链 原型跟原型模式 这一块的知识,主要是设计模式方面的. 首先,我们知道JavaScript是面向对象的.既然是面向对象,那它自然也有相应的类跟对象等概 ...

随机推荐

  1. OpenWRT19.07_命令行_重拨wan_重启路由

    OpenWRT19.07_命令行_重拨wan_重启路由 转载注明来源: 本文链接 来自osnosn的博客,写于 2020-10-19. 写OpenWRT的脚本时,需要用到一些重启命令 以下的命令中的参 ...

  2. [日常填坑系列]CAP食用指南-版本引用问题

    一.前言 最近,由于好久没升级底层框架,一直用着netcore2.2版本,导致有些包没能更新到最新的版本,例如:CAP. 然而,在最近升级到CAP:3.1.2版本的时候,发现有点小坑,只能退回到CAP ...

  3. jenkins 构建历史 显示版本号

    0   jenkins 安装此插件: 此插件名为 " groovy postbuild " 1  效果图: 2   安装插件: 系统管理 --> 插件管理 --> 可选 ...

  4. 【Java】变量

    变量 文章目录 变量 1.变量的概念 2.变量的三要素 3.变量的使用应该注意什么? 4.变量的声明和赋值.使用的语法格式? 5.code 1.变量的概念 变量的作用:变量用来存储数据. 变量的本质: ...

  5. 【Linux】sudo配置文件讲解

    一.sudo执行命令的流程 将当前用户切换到超级用户下,或切换到指定的用户下, 然后以超级用户或其指定切换到的用户身份执行命令,执行完成后,直接退回到当前用户. 具体工作过程如下: 当用户执行sudo ...

  6. 【Jboss】A RESOURCE POOL IS PERMANENTLY BROKEN!

    jboss后台报错,其中有这个错误 [error] A RESOURCE POOL IS PERMANENTLY BROKEN! 查阅多方资料后发现.数据库连接配置文件中,有地方存在空格,导致服务连接 ...

  7. dmp文件导入抽取方法

    一.确认dmp文件.oracle客户端和服务端的字符集 (1)dmp文件字符集确认: 使用UE打开dmp文件查看文件第2个和第3个字节内容,这两个字节记录了dmp文件的字符集.如0354,然后用以下s ...

  8. CTFshow-萌新赛逆向_签退

    查看题目信息 下载re3.pyc文件 使用uncompyle把re3.pyc反编译为re3.py uncompyle6 re3.pyc > re3.py 查看re3.py文件 # uncompy ...

  9. 分布式系统:dubbo的连接机制

    目录 研究这个问题的起因 dubbo的连接机制 为什么这么做 dubbo同步转异步 dubbo的实现 纯netty的简单实现 总结 研究这个问题的起因 起因是一次面试,一次面试某电商网站,前面问到缓存 ...

  10. xtrabakcup基本用法 安装、全量备份恢复、增量备份恢复

    xtrabackup备份原理以及工作流程 备份流程日志分析:1.##读取mysql配置文件2.## 扫描innodb日志lsn并复制inndodb系统表空间3.## 缓冲写出到数据文件并锁表4.## ...