Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >动图学 JavaScript 之:原型继承

动图学 JavaScript 之:原型继承

作者头像
savokiss
发布于 2020-02-18 08:33:45
发布于 2020-02-18 08:33:45
5820
举报
文章被收录于专栏:码力全开码力全开

前言

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

构造函数

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

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

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

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

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

原型继承

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

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

可以看到我们添加的属性有:namebreedcolorbark,但是快看,还有一个 __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.prototypeDog.prototype (当然也有 Object.prototype ,因为 Dog.prototype 是个对象)。

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

原型的终点

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

Object.create

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

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

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

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

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

参考链接

  • JavaScript Visualized: Prototypal Inheritance

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

本文随意转载哈,注明原文链接即可

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码力全开 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
一站搞定原型链:深入理解JavaScript的继承机制
JavaScript 的原型链(prototype chain)是理解 JavaScript 对象和继承机制的关键。它是通过对象的原型(prototype)属性实现的,用于实现对象属性和方法的共享和继承。以下是对 JavaScript 原型链的详细介绍,这一篇文章将会通过理论与demo相结合的方式,力争一文概括原型、对象、原型链以及基于原型链实现JavaScript的继承机制的所有方面,帮助您一站式搞定原型链。
watermelo37
2025/01/22
940
一站搞定原型链:深入理解JavaScript的继承机制
JavaScript学习总结(四)——this、原型链、javascript面向对象
根据题目要求,对给定的文章进行摘要总结。
张果
2018/01/04
1.5K0
JavaScript学习总结(四)——this、原型链、javascript面向对象
原型、原型链和原型继承
上一小节是从继承的层面,介绍原型继承,但是没有具体说什么是原型。只提到构造函数的 prototype, 那么 prototype 是什么?它的作用又是什么?
玖柒的小窝
2021/11/02
7800
原型、原型链和原型继承
如果使用 JavaScript 原型实现继承
在这篇文章中,我们将讨论原型以及如何在 JS 中使用它们进行继承。我们还将会看到原型方法与基于类的继承有何不同。
前端小智@大迁世界
2020/05/12
7100
如果使用 JavaScript 原型实现继承
深入理解JavaScript原型:prototype,__proto__和constructor
JavaScript语言的原型是前端开发者必须掌握的要点之一,但在使用原型时往往只关注了语法,其深层的原理并未理解透彻。本文结合笔者开发工作中遇到的问题详细讲解JavaScript原型的几个关键概念,如有错误,欢迎指正。 1. JavaScript原型继承 提到JavaScript原型,用处最多的场景便是实现继承。然而在实现继承时总有一些细节处理不到位,引起一些看起来莫名其妙的问题。比如使用下述代码: function Animal(){} Animal.prototype = {}; function
寒月十八
2018/01/30
8520
《深入探秘JavaScript原型链与继承机制:解锁前端编程的核心密码》
在JavaScript的奇妙世界里,原型链与继承机制犹如隐藏的宝藏,掌握它们,就如同拿到了开启高效编程大门的钥匙。对于前端开发者来说,这不仅是写出简洁、可维护代码的关键,更是深入理解JavaScript面向对象编程的基石。今天,就让我们一同揭开它们神秘的面纱。
程序员阿伟
2025/04/18
860
《深入探秘JavaScript原型链与继承机制:解锁前端编程的核心密码》
笨办法理解原型链
关于原型链的文章之前写了一篇 https://my.oschina.net/lilugirl2005/blog/1825752
lilugirl
2019/05/28
2990
笨办法理解原型链
让 JavaScript 区别于其它语言的是什么?原型继承!
最近开源了一个 Vue 组件,还不够完善,欢迎大家来一起完善它,也希望大家能给个 star 支持一下,谢谢各位了。
前端小智@大迁世界
2020/12/01
4470
让 JavaScript 区别于其它语言的是什么?原型继承!
JavaScript 进阶教程(3)---让你彻底搞懂原型链和继承
关于原型在JavaScript 进阶教程(1)--面向对象编程这篇文章已经讲过了,今天简单来复习一下。
AlbertYang
2020/09/08
5240
JavaScript 进阶教程(3)---让你彻底搞懂原型链和继承
实现JavaScript继承
使用TypeScript或者ES2015+标准中的extends关键字是很容易实现继承的,但这不是本文的重点。JS使用了基于原型(prototype-based)的继承方式,extends只是语法糖,本文重点在于不使用extends来自己实现继承,以进一步理解JS中的继承,实际工作中肯定还是要优先考虑使用extends关键字的。
雪飞鸿
2020/12/29
6010
《现代Javascript高级教程》JavaScript中的原型与继承
JavaScript是一门支持面向对象编程的语言,它的函数是第一公民,同时也拥有类的概念。不同于传统的基于类的继承,JavaScript的类和继承是基于原型链模型的。在ES2015/ES6中引入了class关键字,但其本质仍然是基于原型链的语法糖。
linwu
2023/07/27
2630
《现代Javascript高级教程》JavaScript中的原型与继承
JavaScript原型与继承
对于使用过基于类的语言 (如 Java 或 C++) 的开发人员来说,JavaScript 有点令人困惑,因为它是动态的,并且本身不提供一个 class 实现。(在 ES2015/ES6 中引入了 class 关键字,但那只是语法糖,JavaScript 仍然是基于原型的)。
用户1428723
2020/08/06
5520
JS进阶:原型与原型链
JavaScript中除了基础数据类型外都是对象(引用类型)。但是由于其没有类(ES6 引入了 class,但其只是语法糖)的概念,为了保证对象之间的联系,就有了原型和原型链的概念。
4O4
2022/04/25
1.5K0
JS进阶:原型与原型链
JS原型继承和类式继承
类式继承(构造函数) JS中其实是没有类的概念的,所谓的类也是模拟出来的。特别是当我们是用new 关键字的时候,就使得“类”的概念就越像其他语言中的类了。类式继承是在函数对象内调用父类的构造函数,使得自身获得父类的方法和属性。call和apply方法为类式继承提供了支持。通过改变this的作用环境,使得子类本身具有父类的各种属性。 var father = function() { this.age = 52; this.say = function() { alert('hello
庞小明
2018/03/07
3.5K0
JS原型继承和类式继承
JavaScript继承背后的场景-prototype,__proto__, [[prototype]]
每个对象都可以有另一个对象作为其原型。然后前一个对象继承了它的所有原型属性。对象通过内部属性[[Prototype]]指定其原型。由[[Prototype]]属性连接的对象链称为原型链。
前端迷
2019/07/27
6610
深入理解原型和继承
这几天在掘金上阅读到了一篇关于原型的文章,角度较之前看到的几篇博客都不一样,顿时感觉我对于原型的知识点还没有完全吃透。鉴于本篇文章很可能会进行不定期的修订和拓展,故在此附上更新日志,以简单记录我在学习上的认知更新。
Chor
2019/11/07
4740
深入JavaScript原型链污染
相比其他语言(如Java、python等传统OOP语言),JavaScript的机制和类完全不同。
raye
2024/02/04
2301
一篇JavaScript技术栈带你了解继承和原型链
在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则。
达达前端
2019/11/19
4650
JavaScript学习笔记022-原型链0原型继承0对象的深浅拷贝extends
Author:Mr.柳上原 付出不亚于任何的努力 愿我们所有的努力,都不会被生活辜负 不忘初心,方得始终 这几天一直在做node项目实训 学到了很多实际企业开发知识 学的东西 跟要运用起来的东西 就好像教会你1+1=2 然后让你做高等代数 还需要加倍的努力啊 兄弟 <!DOCTYPE html> <!-- 文档类型:标准html文档 --> <html lang='en'> <!-- html根标签 翻译文字:英文 --> <head> <!-- 网页头部 --> <meat charset='UTF
Mr. 柳上原
2018/09/05
4200
[我的理解]Javascript的原型与原型链
一、原型与原型链的定义 原型:为其他对象提供共享属性的对象     注:当构造器创建一个对象,为了解决对象的属性引用,该对象会隐式引用构造器的"prototype"属性。程序通过constructor.prototype可以直接引用到构造器的"prototype"属性。并且添加到对象原型里的属性,会通过继承与所有共享此原型的对象共享。 原型链:每个由构造器创建的对象,都有一个隐式引用(叫做对象的原型)链接到构造器的"prototype"属性。再者,原型可能有一个非空隐式引用链接到它自己的原型,以此类推,这叫
sam dragon
2018/01/17
8840
[我的理解]Javascript的原型与原型链
相关推荐
一站搞定原型链:深入理解JavaScript的继承机制
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档