理解js中原型链的封装继承多态

news2025/2/24 5:58:59

前言

面向对象有三大特性:封装继承多态。

不过,js和java的封装继承多态是不一样的,我和从事java开发的朋友有过一次对话(抬杠 !--)。

我说:javascript也是面向对象语言,

他说:不对吧,js不是面向对象吧。

我说:是的,官方说的就是面向对象语言。

他说:那你知道三大特性吗?

我说:封装继承多态。

然后他说:那你说一下那都是啥意思。

我说:构造函数...原型对象...原型链....

他说:你说的这都是啥呀,构造函数和原型链是啥,听都没听过,面向对象使用类,你那js是假的面向对象吧。

我说:js后面用的是类,但在类之前用的是原型链。其实,类也是原型链的语法糖,不归根到底还是原型链吗。

因为我不懂java,他不懂js。不过js确实和java在面向对象的实现上是不一致的,js在class出来之前,是通过原型链的特性实现了面向对象编程。

家有儿女

今天这篇文章,我用《家有儿女》来通俗的说一下js中原型链是怎么完成封装继承多态的,class相关的这篇文章不提。

构造函数构建家庭成员

        function Family(name, gender, token) {
            //姓名
            this.name = name
            //性别
            this.gender = gender
            //身份
            this.token = token
            //家里有好多本书
            this.bookList = ['资治通鉴', '百家菜谱', '七龙珠', '三体']
            //家里的厨房可以用来做饭
            this.useChuFang = function (type, name) {
                console.log(`我用${type}做出了我想吃的${name}`)
            }
            //使用电脑
            this.computer = function (type) {
                //电脑有显卡,键盘,内存条,处理器等
                let xianka = () => { }
                let jianpan = () => { }
                let chuliqi = () => { }
                let write = () => {
                    console.log(`我是${this.name},我会用电脑写小说`)
                }
                let playGame = () => {
                    console.log(`我是${this.name},我会用电脑打游戏`)
                }
                switch (type) {
                    case "write":
                        write()
                        break
                    case "playGame":
                        playGame()
                        break
                    default:
                        console.log(`我是${this.name}抱歉,我不懂电脑的构造和具体原理`)
                }
            }
            //使用化妆品
            this.useHuaZhuangPin = function(){
                if (this.gender === 'woman') {
                    console.log(this.name,'你是女性,可以使用这些化妆品')
                } else {
                    console.log(this.name,'男人就别作妖了')
                }
            }
            //私有变量,10瓶饮料
            drinks = 10
            //闭包返回函数
            let fn = (num,name, drinks) => {
                if(drinks>-1){
                    console.log(`我是${name},我拿了${num}瓶饮料,还剩${drinks}瓶饮料`)
                }else{
                    console.log(`我是${name},我想拿饮料,发现没了`)
                }
                
            }
            //闭包封装私有变量,家里的饮料
            this.drinkFun = (num,name) => {
                drinks = drinks - num
                return fn(num,name, drinks)
            }
                        //家庭有一笔1百万的存折
                         bankBook = 1000000
        }



        let XiaDongHai = new Family('夏东海', 'man', '父亲')
        let XiaoXue = new Family('小雪', 'woman', '女儿')
        let LiuMei = new Family('刘梅', 'woman', '母亲')
        let LiuXing = new Family('流星', 'man', '儿子')
        console.log(XiaDongHai, '夏东海')
        console.log(XiaoXue, '小雪')
        console.log(LiuMei, '刘梅')
        console.log(LiuXing, '流星')
测试

结论:

一个构造函数就像是一个家庭,这个家庭有一些资产,是大家所共有的,每个家庭成员都可以去使用和调配这些资产,每个家庭成员都有原型链定义的方法属性和自己独有的属性。

封装

        //1.构造函数封装公共方法
        //夏东海用电脑写文章
        XiaDongHai.computer('write')
        //流星用电脑打游戏
        LiuXing.computer('playGame')
        //你问他们电脑的显卡原理是什么
        XiaDongHai.computer('xiaka')
        //他们虽然不懂电脑是怎么运行的,但是他们可以用电脑做到自己想做的事。

        //2.闭包封装私有变量
        //全家喝饮料
        XiaDongHai.drinkFun(3,'夏东海')
        LiuMei.drinkFun(2,'刘梅')
        LiuXing.drinkFun(4,'流星')
        XiaoXue.drinkFun(1,'小雪')
        XiaDongHai.drinkFun(1,'夏东海')
测试

 结论

构造函数内部可以封装公共属性方法,闭包可以封装私有变量,都可以让所有的实例对象去操作这些属性方法,并且无需知道这些属性方法是内部是如何构造的。

公共资产只要你是这个家庭成员,你就可以用它。你可以不用知道这个东西的构造原理是什么,你只需要会使用它。

你不需要会包饺子,你只需要会吃饺子

继承

        
        //给构造函数,也就是全家添加100万元的家庭资产和一辆奔驰轿车
        Family.prototype.bankBook = 1000000
        Family.prototype.car = '奔驰'

        //接下来我就用代码来清晰的展示面向对象的这些特征
        //构建家庭成员,其实构造函数的本质作用,就是用来批量创建一些拥有相同属性或者方法的对象,不让代 
        码大量冗余重复。
        let XiaDongHai = new Family('夏东海', 'man', '父亲')
        let XiaoXue = new Family('小雪', 'woman', '女儿')
        let LiuMei = new Family('刘梅', 'woman', '母亲')
        let LiuXing = new Family('流星', 'man', '儿子')

 测试
      
        //夏东海将原来的奔驰车卖掉了,换了一辆新宝马车,花了10万元
        Family.prototype.car = '宝马'
        console.log(Family.prototype.bankBook,'???')
        Family.prototype.bankBook = Family.prototype.bankBook - 100000
  
        console.log(XiaDongHai.car,XiaDongHai.bankBook,'夏东海')
        console.log(LiuMei.car,LiuMei.bankBook,'刘梅')

 

 结论

  原型链可以添加,重写一些公共属性,所有实例对象继承原型对象的属性都会受到影响。

  夏东海花了家里的公共财产,所有家庭成员拥有的共同财产就会减少。但是买了新车,以后所有成员就都能坐上宝马新车了。

同甘共苦

多态

        //夏东海和刘梅做饭
        LiuMei.useChuFang('鸡块','大盘鸡')
        XiaDongHai.useChuFang('方便面','泡面')
        //流星和小雪化妆
        LiuXing.useHuaZhuangPin()
        XiaoXue.useHuaZhuangPin()
测试

结论

不同的方法被不同的对象调用,结果会多样性。

龙生九子各不同

结束语

其实我说的也不是很详尽,只是想变着法的想让看客明白原型链的具体作用和实际运用方法,熟练理解原型链是js开发者最重要的技能之一,现在你可以想一下vue是不是也是使用原型链的特性去让各组件操作原型上的实例方法呢。

更多继承方法请看:

js中继承的方法-CSDN博客

感觉有用的给个赞吧!

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

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

相关文章

彼此的远方

那天两个人互相表白了心意,在那天那刻确定了彼此相爱,没有鲜花,没有礼物。 男孩的世界曾陷入黑暗,冷清而又孤寂,女孩带着光和热来了,后来,女孩成为了男孩的太阳。女孩以为男孩是远方的风…

SpringBoot 注入RedisTemplat 启动报错

需求 因为需要限制部门内多个人员同一时间操作同一批客户的需求,考虑下决定用Redis滑动窗口实现自过期以及并发校验。 问题 新建了个Redis工具类封装RedisTemplat 操作,到启动时却发现无法正常启动,报错注入错误。 The injection point has…

数字化转型:互联网+为企业带来的全新机遇

引言 在当今快速发展的商业环境中,数字化转型和互联网已成为企业前进的关键动力和重要战略。数字化转型代表了企业在数字技术的推动下,对其运营模式、业务流程以及客户体验的全面变革和升级。而“互联网”则突显了数字化时代与传统产业的融合&#xff0…

RAR文件的密码保护如何设置和取消?

RAR文件是压缩包一种常用的压缩文件格式,对于这种文件,我们如何设置和取消密码保护呢? 首先我们要下载适用于RAR文件的WinRAR解压缩软件,然后在压缩文件的时候,就可以同步设置密码,选中需要压缩的文件&…

navicat premium 历史版本下载地址

navicat贴心地给大家准备了一致的下载地址: 只是没有把旧版本的链接放出来而已。 链接的格式 : 前缀版本类型语言位数 前缀:http:/download.navicat.com/download/navicat 版本:三位数,前两位是大版本,后…

微信小程序之猜数字和猜拳小游戏

目录 效果图 app.json 一、首页(index3)的代码 wxml代码 wxss代码 二、猜数字页面(index)代码 wxml代码 wxss代码 js代码 三.游戏规则页面(logs)代码 wxml代码 wxss代码 四.猜拳页面&#xff…

软件设计模式原则(五)接口隔离原则

顾名思义,该原则说的是:客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。 一.定义 核心思想: 使用多个专门的接口比使用单一的总接口要好。一个类对另外一个类的依赖性应当是建立在最小的接口上的。一个接口…

Leetcode题库(数据库合集)_ 难度:困难

目录 难度:困难1. 部门工资前三高的所有员工2. 行程和用户3. 体育馆的人流量4. 员工薪水的中位数5. 同一天的第一个电话和最后一个电话6. 查询员工的累计薪水7. 给定数字的频率查询中位数8. 学生地理信息报告9. Hopper 公司查询 ①10. 职员招聘人数11. 职员招聘人数…

【AXI死锁】

单主机单从机死锁 AXI4没有WID,所以比较严格,即写数据通道的数据必须严格的按照写地址通道的数据顺序传送,比如AW通道发送ADDR0,ADDR1,ADDR2三笔写操作,每个写操作burst length=2,那么W通道的顺序在AXI4协议的规定下必须为:WDATA0_0,WDATA0_1,WDATA1_0,WDATA1_1,WDATA2_0…

Linux last命令教程:如何查看用户的登录和注销历史(附案例详解和注意事项)

Linux last命令介绍 last命令在Linux中用于显示自文件/var/log/wtmp创建以来所有用户的登录和注销列表。可以给出一个或多个用户名作为参数,以显示他们的登录(和注销)时间和主机名。 Linux last命令适用的Linux版本 last命令在大多数Linux…

不知道如何制作电商产品说明书?推荐一个很好的方法!

作为一名电商从业者,你可能会经常面临一个问题:如何制作一份详细且吸引人的产品说明书?这的确是一个棘手的问题,因为产品说明书不仅要准确地描述产品的特点和功能,还要能够吸引潜在客户的注意。 一、电商网站制作产品说…

七、三台虚拟机JDK环境安装

目录 1、在三台机器上分别创建安装目录

一套rk3588 rtsp服务器推流的 github 方案及记录 -01

我不生产代码,我只是代码的搬运工,相信我,看完这个文章你的图片一定能变成流媒体推出去。 诉求:使用opencv拉流,转成bgr数据,需要把处理后的数据(BGR)编码成264,然后推流…

第三方支付原理

1.什么是第三方支付 所谓第三方支付,就是一些和各大银行签约、并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台。在通过第三方支付平台的交易中,买方选购商品后,使用第三方平台提供的账户进行货款支付,由第三方通知卖…

微信小程序基础

1.小程序发展史 微信小程序之前,是使用weixin-sdk进行开发,调用视频,摄像头等。 微信小程序weixin up端,所以PC端的window这些没有,运行环境是IOS,安卓等,有一些特殊的调用录音功能&#xff0…

百元开放式蓝牙耳机哪款好、热门高性价比开放式推荐

在众多耳机类型中,开放式耳机正逐渐崭露头角。它们融合了音质和佩戴舒适性,能给你带来全新的佩戴感受。这些耳机不仅提供高品质的音响体验,还让你能够在户外佩戴欣赏音乐的同时保持对周围环境的感知,更加安全、保障。 在本文中&a…

分布式版本管理系统---->Git(Linux---centos(保姆式)讲解1)

文章目录: 1:什么是Git以及作用 2.Git的基本操作过程(创建git仓库,配置仓库的配置) 3.git的工作区,暂存区,版本库的关系 4.将文件添加到版本库:git add 与git commit -m命令 5.git log查看日志的引入 6.查看.git文件中的内容 7.修改文件内容查…

从浅入深掌握进阶结构体(C语言)

前言 这一期我们将继续讲解结构体的知识,还没有看过上一期的小伙伴一定要赶紧去学习哦。 上一期,冲鸭! 那么话不多说我们开始今天的学习吧! 文章目录 1,结构体的自引用2,匿名结构体3,位段4,结构体的传参5,尾声 1,结构体的自引用 …

SqlServer存储过程中使用in

第一步:创建测试存储过程: CREATE PROCEDURE [dbo].[test] deptCode varchar(MAX)AS BEGINSELECT * from DEPT_INFO_A where DEPT_CODE in (deptCode)END 此存储过程只是一个简单的查询 第二步测试: 传入的 deptCode为:101200…

苍穹外卖项目笔记(7)— 微信登录、商品浏览

前言 苍穹外卖项目代码:https://github.com/Echo0701/take-out 1 HttpClient 1.1 介绍 HttpClient 是 Apche Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且支持 HTTP 协议最新…