动图学 JavaScript 之:原型继承

前言

你是否曾思考为什么我们能使用 JS 中的一些内置属性和方法,比如 .length.split().join()?我们并没有显式地声明它们,那么究竟它们从哪里来的呢?可不要说什么“那是 JS 中的魔法!”。其实这些都因为一个叫做 原型继承(prototypal inheritance) 的东西。它太棒啦,你平时也经常会用到,只不过可能没有注意!

构造函数

我们经常需要创建很多相同类型的对象。想象一下我们有个网站,上面都是狗狗~

对于每个狗狗来说,我们需要一个对象来表示它!为了不每次都新创建一个对象,就需要写一个构造函数(稍后再说 ES6 中的类哈~)。有了构造函数,就可以用 new 关键字来创建狗狗的 实例(instance) 了。

每只狗都有一个 名字(name)品种(breed)颜色(color) 和一个 吠(bark) 方法。

当我们创建了这个 Dog 构造函数,它并不是我们创建的唯一对象(要知道函数也是对象)。自动地,我们创建了另一个 prototype 对象。默认情况下,这个对象有一个 constructor 属性,指向的就是我们的 Dog 构造器。

这个在 Dog 构造器上的 prototype 属性是不可枚举的,意味着当你尝试访问对象属性时,该属性不会显示。但是它仍然在那里!

原型继承

好吧~那么为什么需要有该属性对象呢?首先,让我们来创建几只狗狗。简单起见,我们就叫它们 dog1 和 dog2dog1 叫 Daisy,是一只可爱的拉布拉多(Labrador)!dog2 叫 Jack,是一只勇敢的杰克罗素犬(Jack Russell)~

让我们将 dog1 打印到控制台,然后展开它的属性:

可以看到我们添加的属性有:namebreedcolor 和 bark,但是快看,还有一个 __proto__ 属性!它也是不可枚举的,所以通常我们在获取对象属性的时候也看不到它。让我们展开看看:

是不是看起来和 Dog.prototype 一样哈!你猜怎么着,这个 __proto__ 就是对 Dog.prototype 的引用。这就是 原型继承 的全部内容:构造函数创造的每个实例都能够访问构造函数的原型。

原型继承的好处

那么为什么这很酷?有时候我们拥有每个实例共享的属性。比如 bark 方法:它在每个实例中都是相同的,那为什么每次创建新实例都要新建一个 bark 方法,很明显这样会浪费内存。相反地,我们可以将 bark 方法添加到 Dog.prototype 上去!

这样每当我们访问实例的属性时,引擎首先检查该属性在实例上是否定义,如果没有找到,就会通过 __proto__ 属性,顺着原型链 继续查找。

不止是一层

这只是一个步骤,其实可以包含多个步骤!如果继续进行下去,你可能会注意到,当我展开 Dog.prototype 的 __proto__ 对象时,我没有包含一个属性。由于 Dog.prototype 自己也是一个对象,这意味着它实际上是 Object 构造函数的实例。这意味着 Dog.prototype 也有一个 __proto__ 属性,并且指向了 Object.prototype 。

比如说 .toString() 这个方法。它是定义在 dog1 上么?明显不是。那么在 Dog.prototype 上有么?也没有!其实它是定义在 Dog.prototype.__proto__ 上,即 Object.prototype 上。

ES6 中的类

前面我们使用的是构造函数的方式(function Dog() { ... }),实际上 ES6 中提供了构造函数和原型的更简单的语法:类(Classes)

 只是 构造函数 的 语法糖。一切都是以相同的方式工作!

我们使用 class 关键字来定义类。每个类都有一个 constructor 函数,基本上对应了 ES6 中构造函数的写法。而我们想要添加到原型 prototype 上的属性和方法,都可以在类中直接定义。

关于类的另一个好处就是,我们可以轻松地 扩展(extend) 其他的类。

类的继承

假如我们要添加另一种狗,吉娃娃(Chihuahuas)狗。为了便于理解,我们只添加一个 name 属性。但是吉娃娃也可以有自己特殊的叫声!和普通的叫声不同,吉娃娃的叫声可能比较小~

在子类中,我们可以通过 super 关键字访问到父类的构造方法。参数当然也参考父类的构造方法传入。

myPet 可以访问到 Chihuahua.prototype 和 Dog.prototype (当然也有 Object.prototype ,因为 Dog.prototype 是个对象)。

由于 Chihuahua.prototype 上有一个 smallBark 方法,Dog.prototype 上有一个 bark 方法,所以我们可以在 myPet 实例上同时访问到 smallBark 和 bark 方法。

原型的终点

现在,你可以想象,原型链不会永远持续下去。最终会有一个原型等于 null 的对象:它就是 Object.prototype。如果我们试图访问在本地或者原型链上都不存在的属性,最终会返回 undefined

Object.create

尽管上面已经解释了构造函数和类,其实还有一个为对象添加原型的方式是使用 Object.create 方法。通过这个方法,我们创建了一个新对象,并且指明了这个对象的原型是什么。

只需要将一个已经存在的对象传入 Object.create 方法中。创建出来的对象就是以我们传入的对象作为原型。看例子:

我们打印一下 me ,可以看到:

我们并没有为 me 对象添加其他的属性,但是访问它却有一个 __proto__ 属性,并且这个属性指向的是具有 name 和 age 的对象 person。而 person 这个对象的 __proto__ 属性指向的是 Object.prototype

全文就到这里啦,希望对你学习原型继承有帮助~

本文是翻译的系列文章:

  • 动图学 JS 之:声明提升(Hoisting)

  • 动图学 JS 之:作用域链(Scope Chain)

  • 动图学 JS 之:事件循环(Event Loop)

  • 动图学 JS 之:JavaScript 引擎原理

  • 动图学 JS 之:原型继承 【本篇】

参考链接

  • JavaScript Visualized: Prototypal Inheritance


本文首发于公众号:码力全开(codingonfire)

本文随意转载哈,注明原文链接即可,公号文章转载联系我开白名单就好~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1381524.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

顺风车撑起100亿估值,嘀嗒是怎样“闷声发大财”的?

6月30日晚,滴滴“低调”挂牌纽交所,摘得国内“共享出行第一股”的桂冠,在今年轰轰烈烈的网约车企业上市浪潮中领跑。而曾对“共享出行第一股”跃跃欲试的嘀嗒出行,虽然在冲击IPO的路上起步最早,但上市之路却颇为忐忑&a…

嘀嗒出行IPO 会成为出行界的“拼多多”吗

出行界,都快忘了嘀嗒。 可以说,相比于行业老大滴滴,嘀嗒并不怎么亮眼。但是谁也没有想到,6年后,嘀嗒华丽的一个转身,就是在去IPO的路上。 闷声做事的嘀嗒真的值得IPO吗?此时IPO又暗藏什么玄机…

sklearn中的线性回归大家族

1 概述 1.1 线性回归大家族 回归是一种应用广泛的预测建模技术,这种技术的核心在于预测的结果是连续型变量。决策树、随机森林、支持向量机的分类器等分类算法的预测标签是分类变量,多以{0,1}来表示,而无监督学习算法(如CPA、Km…

十二星座神话故事

对于西方的星座,绝大部分都有很多精彩的希腊神话故事。边看神话边记星座是一种非常好的方法。推荐对于爱好天文的孩子,可以购买一些希腊神话书籍。这样从最浅显的星座知识入手,讲述怎样观测、认识恒星,地球与天体的视运动&#xf…

主流计算机编程语言之父---集锦

主流计算机编程语言之父---集锦 收藏 1)J. Backus的FORTRAN语言 早期电脑都直接采用机器语言,即用“0”和“1”为指令代码来编写程序,难写难读,编程效率极低。为了方便编程,随即出现了汇编语言,虽然提高了效率&am…

26岁离开谷歌,女朋友一个建议助他开发出10亿美元App

作者:Alan Trapulionis 链接:https://entrepreneurshandbook.co/26-year-old-coder-built-a-1-billion-app-in-2-years-after-following-his-girlfriends-advice-c6f378db1fd1 前言 Kevin Systrom 沮丧地离开了谷歌。 Kevin 在谷歌担任产品经理近三年之久…

Python 基础 之 jupyter notebook 中机器学习的简单入门书写数字识别 demo 操作学习

Python 基础 之 jupyter notebook 中机器学习的简单入门书写数字识别 demo 操作学习 目录

【机器学习实战】使用sklearn中的线性回归LinearRegression对加利福尼亚房价进行预测

1.数据集 特征值 共有20640条数据,8个特征。 目标值 2.代码实现 2.1 回归预测 from sklearn.datasets import fetch_california_housing as fch # 大数据集,需要下载,加利福尼亚房价数据集 from sklearn.model_selection import train_…

回归预测4:机器学习处理加利福尼亚房价数据集

目录 1 介绍2 工具箱导入3 导入数据 数据分析4 拆分标签和特征5 ocean_proximity特征编码6 划分训练集-测试集7 模型训练和验证 1 介绍 我们使用California Housing Prices数据集进行预测,数据集地址:https://download.csdn.net/download/ww596520206/8…

AgentBind--Deepneuralnetworksidentifysequencecontextfeaturespredictiveoftranscriptionfactorbinding

推荐度:⭐⭐⭐⭐⭐亮点 设计了一种机器学习构架AgentBind,可以识别和解释对于转录因子(TF)结合最重要的序列特征。与以往大多数研究结合基序的系统或程序不同,AgentBind着眼于基序附近的序列背景,并可以研究…

VGG16论文解读

VGGNET VGG16相比AlexNet的一个改进是采用连续的几个3x3的卷积核代替AlexNet中的较大卷积核(11x11,7x7,5x5)。对于给定的感受野(与输出有关的输入图片的局部大小),采用堆积的小卷积核是优于采用…

机器学习 加利福尼亚房价预测

学习目标: 提示:导入包 例如: import pandas as pd import numpy as npfrom sklearn.datasets import fetch_california_housing from sklearn.model_selection import KFold, train_test_split from sklearn.metrics import mean_squared…

目前加尼福尼亚自动驾驶公司测试公司————20150529

获准在加州测试自动驾驶汽车的公司 科技公司和汽车制造商正在竞相开发能够自主驾驶,不需要人类干预的汽车。市场对于这类汽车的兴趣已经协助刺激了人工智能和汽车专业人士的需求。无人车开发是一个耗费资金的项目,这可能会让部分风险投资家望而却步。 Z…

Python学习-KNN预测加尼福尼亚房价

加尼福尼亚房价数据集与KNN 需要的几个Python库 import matplotlib.pyplot as plt from sklearn import datasets from sklearn.neighbors import KNeighborsRegressor from sklearn.cross_validation import train_test_split from sklearn.metrics import mean_squared_e…

梅尔加尼服务器状态,梅尔加尼服务器第二界闪光平原暴力竞走大赛

梅尔加尼服务器第二界闪光平原暴力竞走大赛 (2006-12-12 10:27:42) 主办方:艾泽拉斯皇家记者协会 协办方:帕兰萨斯(LM)/同心盟(BL) 公会 奖品提供:第九城市 服务器:二区梅尔加尼 时间:2006年12月17日 下午2点进场地 2.30预赛开始 比赛规则:http://blog.sina.com.cn/u/47d86f7f0…

车载Tbox-CAN终端数据采集实现方案

因工作关系有机会与一家做汽车数据采集公司的Tbox终端产品做数据对接。 这个产品通过can口与汽车总线交换数据,再将采集的数据打包通过4G以tcp报文发送到云端。云端通过解析、格式转换后保存到数据库。 本文介绍用nodejs实现tcp报文的解析,报文描述如下…

如何做好 PHP 项目文档管理?PHPer 开发的必备利器!

对于常年写 PHP 的老司机来说,PHPDoc 一定不会陌生,不过从1.3.0开始,更名为 phpDocumentor。它作为一个用 PHP 写的工具,主要作用是从你的源代码的注释中生成文档,因此在给你的程序做注释的过程,也就是你编…

PHP读取word文档 导入word文档

PHP读取word文档 导入word文档 PHP读取word文档 导入word文档libreoffice把word转html用phpquery读取html的内容 PHP读取word文档 导入word文档 前一段时间在工作中遇见了一个棘手的需求,客户要求把word里的数据导入,对数据进行统计。 刚开始觉得挺简单…

开发文档(PHP代码规范)

为什么80%的码农都做不了架构师?>>> 1 框架目录及结构简介 1.1 目录结构 1.2框架简介和主要目录结构简介 1.2.1 框架版本采用:Lumen (5.5.2) (Laravel Components 5.5.*)版本 参考链接:https://lumen.laravel-china.org/docs/5.2…

PHP编码规范文档

为了提高工作效率,保证开发的有效性和合理性,并最大程度提高程序代码的可读性和可重复利用性,提高沟通效率,需要一份代码编写规范。让大家养成良好的代码编写习惯,同时减少代码中的bug。 CleverCode整理了一些规…