理一理 Javascript 的原型链

本贴最后更新于 2965 天前,其中的信息可能已经东海扬尘

理一理 Javascript 的原型链

特别感谢 JS 核心系列:浅谈原型对象和原型链给了我很大的启发!本文也是基于此文自己动手做了实验,并得到了相似的结果,遂与大家分享。

Javascript 中,大致存在两种对象:普通对象和函数对象。
一般而言,通过 new Function() 创建的对象是函数对象,其他的是函数对象。

// a function func1() {} // b var func2 = function() {} // c var func3 = new Function()

a 和 b 在创建的时候,JS 会自动通过 new Function() 来创建对象,所以 a,b,c 都是通过 new Function() 创造的函数对象。

// o1 var o1 = {} // o2 var o2 = new Object(); // o3 var o3 = new func1();

o1, o2 是使用对象字面量的形式创建的普通对象。
o3 不是通过 new Function() 的形式创建的对象,所以也是普通对象。

每当创建函数对象时,该对象中都会内置一些属性,其中包括 prototype__proto__prototype 即为原型对象
其内记录着函数对象的一些属性和方法。

function f1() {} f1.prototype.foo = "bar"; console.log(f1.prototype); // Object {foo: "bar", constructor: function} console.log(f1.foo); // undefined

prototypef1 不可见。也就是说,f1 在调用自身属性或方法时不会查找 prototype 内的属性和方法。
调用

prototype 的主要作用是继承。prototype 内定义的属性和方法都是留给自己的后代使用的。
说到后代,就必须说说 js 中的原型链。此时,另一个属性 __proto__ 就登场了。
__proto__ 的作用是保留父类的 prototype 对象。
js 在使用 new 表达式创建对象时,会将父类的 prototype 赋值给新对象的 __proto__。这样就形成了代代继承。

var obj = new f1(); console.log(obj.foo); // "bar" console.log(obj.__proto__); // Object {foo: "bar", constructor: function} console.log(obj.__proto__ == f1.prototype); // true

结果
现在我们知道,obj 中的 __proto__ 保存的是 f1 中的 prototype。即创建出的普通对象的 __proto__ 等于创建其的函数对象的原型。

那么 f1prototype__proto__ 又是什么呢?

console.log(f1.prototype.__proto__ == Object.prototype); // true console.log(Object.prototype.__proto__); // null

结果 2
可以看出,f1prototype__proto__ 指向了 Objectprototype,而 Objectprototype__proto__null
可以通过以上示例画出一条非常清晰的链式调用,此链即为 “原型链”。
原型链
在拥有这样一条原型链之后,当 obj.foo 执行时,会先查找自身是否有该属性(不会查找 prototype)。如果没找到,则会沿着原型链依此去查找。
在上例中,我们将 foo 定义在 f1prototype 上,obj.foo 在调用时就在原型链中找到了 foo 这个属性并执行。

总结:

  1. 原型链真正的形成靠的是 __proto__ 而非 prototypejs 在执行对象方法时会查找对象自身是否有该方法,如果不存在,会在原型链上找而不会在自身的 prototype 上找。
  2. 如果 __proto__ 改变则整条原型链都会发生改变,等于改变了对象的数据类型。
  3. 函数的 prototype 不属于自身的原型链。
  4. 在原型对象(prototype)上定义方法和属性是为了被子类继承和调用。

测试用代码可以在我的 github 上下载,我一直相信,自己动手去测试才是掌握知识点的最好方法。

  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    730 引用 • 1281 回帖 • 4 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    246 引用 • 1338 回帖 • 2 关注
  • 研究
    12 引用 • 34 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
zjhch123
未来的事无人知晓,所以才有无穷可能。 杭州

推荐标签 标签

  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 616 关注
  • 导航

    各种网址链接、内容导航。

    45 引用 • 177 回帖
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    240 引用 • 224 回帖
  • 博客

    记录并分享人生的经历。

    273 引用 • 2388 回帖 • 1 关注
  • OneNote
    1 引用 • 3 回帖 • 1 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 542 关注
  • 叶归
    11 引用 • 52 回帖 • 20 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    125 引用 • 74 回帖 • 3 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    188 引用 • 319 回帖 • 241 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 489 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 364 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25971 引用 • 107699 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖
  • 倾城之链
    23 引用 • 66 回帖 • 170 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    32 引用 • 99 回帖 • 1 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖
  • sts
    2 引用 • 2 回帖 • 241 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 642 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 36 关注
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 3 关注
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 119 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 224 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 110 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖 • 2 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 568 关注
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖 • 3 关注