当前位置: 首页 > news >正文

数组中的各种迭代API方法手写

js的数组上有很多实用的方法,不论是在遍历数组上,还是在操作数组内元素上,它有许多不同的遍历数组的方法,同时它还有着可以直接操作数组中间元素的方法。

接下来,我来带大家手写数组里的 遍历方法

Array.forEach()

首先, Array.forEach() 接收一个回调作为参数;

同时,在它的回调则接收三个参数,分别代表着(数组项,下标,整个数组本身);

最后,forEach 会把数组进行遍历调用这个传进去的回调函数。

例如:

const singer = [{ name: '周杰伦', num: 20 },{ name: '许嵩', num: 25 },{ name: '林俊杰', num: 19 },{ name: '蔡徐坤', num: 10 },{ name: '鹿晗', num: 0 },
];singer.forEach((item, index, arr) => {console.log(item, index, arr);
})// 输出
// { name: '周杰伦', num: 20 },0, [{ name: '周杰伦', num: 20 },{ name: '许嵩', num: 25 },{ name: '林俊杰', num: 19 },{ name: '蔡徐坤', num: 10 },{ name: '鹿晗', num: 0 }]
// { name: '许嵩', num: 25 },1,[{ name: '周杰伦', num: 20 },{ name: '许嵩', num: 25 },{ name: '林俊杰', num: 19 },{ name: '蔡徐坤', num: 10 },{ name: '鹿晗', num: 0 }]
// ...
// ...
// ... 

知道了 Array.forEach() 接收的参数以及怎么执行的,那么我们就可以开始手写它了。

Array.prototype.my_forEach = function(callback) {//将我们手写的方法定义在Array的原型上,接收一个callback回调for (let i = 0; i < this.length; i++) { //遍历这个数组,同时在遍历里面调用这个接收到的回调callback(this[i], i, this)}
} 

相对于其它数组遍历方法,forEach方法应该是最简单的一种方法了,没有很特殊的地方,只是简简单单的遍历数组里每一个元素,传递出来。

Array.map()

Array.map() 方法跟 Array.forEach() 方法接收的参数相似;

也是接收一个回调,回调里也是接收那三个参数,分别代表着(数组项,下标,整个数组);

但是它跟 Array.forEach() 还是有一个差别;

那就是它会返回出来一个数组,返回出来的数组的每一项都是回调里面返回出来的值。

例如:

const singer = [{ name: '周杰伦', num: 20 },{ name: '许嵩', num: 25 },{ name: '林俊杰', num: 19 },{ name: '蔡徐坤', num: 10 },{ name: '鹿晗', num: 0 },]const newSinger = singer.map((item, index, arr) => {return item})console.log(newSinger); 

打印出来的结果会是:

那么知道了 Array.map() 的特性之后,我们完全可以开始手写它了,

Array.prototype.my_map = function(callback) { // 写一个my_map方法写在Array原型上,接收一个回调const res = []//定义一个数组,用来接收遍历回调得到的新的返回值,最后返回出去for (let i = 0; i < this.length; i++) {res.push(callback(this[i], i, this))//把回调返回出来的值往res数组添加}return res //返回出去数组res
} 

Array.map() 相对于普通的遍历来说,它只是会返回出来一个数组,用来接收每个回调的返回值。

Array.filter()

Array.filter() 方法跟 Array.map() 方法接收的参数一样,也是接收一个回调;

回调里同样也是接收那三个参数,分别代表着(数组项,下标,整个数组);

同时它跟 Array.map() 一样,它也会返回出来一个数组;

但是不一样的是,它会对数组每一项进行筛选(故我们通常会叫 filter 叫筛选器方法);

筛选的条件就是回调函数里的 return 所返回出来的条件。

例如:

const singer = [{ name: '周杰伦', num: 20 },{ name: '许嵩', num: 25 },{ name: '林俊杰', num: 19 },{ name: '蔡徐坤', num: 10 },{ name: '鹿晗', num: 0 },]const newSinger = singer.filter((item, index, arr) => {return item.num > 15})console.log(newSinger);//打印结果:// [{ name: '周杰伦', num: 20 },//{ name: '许嵩', num: 25 },//{ name: '林俊杰', num: 19 }] 

这里我们用官方的 Array.filter() 方法,在里面返回的条件是 item.num>15 ;

所以我们打印用来接收 filter 返回出来的那个数组,可以看到的是打印的是:

[{ name: '周杰伦', num: 20 }, { name: '许嵩', num: 25 }, { name: '林俊杰', num: 19 }]

打印出来的这个数组里每一个元素都是满足 item.num>15 这个条件的数组项;

所以我们如果想写一个 filter 方法的话,目标就很明确了,我们需要满足:

1.遍历这个数组的同时拿回调函数里返回出来的判断条件来判定数组项是否满足条件2.满足条件的数组项我们就把它放到一个新数组里去,用于最后返回出来那么知道这些,我们就可以很轻松的把这个方法手写出来了:

Array.prototype.my_filter = function(callback) {const res = [];//定义一个空数组,用来装满足判定条件的数组项for (let i = 0; i < this.length; i++) { //遍历回调callback(this[i], i, this) && res.push(this[i]) //语句判断,如果满足回调函数返回出来的判定条件,就把数组该项加入res数组}return res//返回出来满足条件的数组
} 

Array.every()

Array.every() 方法与其它数组方法接收的参数也是基本一致,不同的是它是返回出来一个 boolean 值;

应用场景一般是发生在检查所有数组值是否通过测试;

一旦有一个值不通过,那么就会直接返回 false,只有所有值都满足条件,才会返回 true。

根据这些条件我们就可以有了大致方向:

1.对数组每一项进行条件判断,只有一个不满足,直接 return false2.循环结束后加一个 return true 用于返回当所有情况都满足了,那么返回 true```
Array.prototype.my_every = function(callback) {for(let i = 0 ; i < this.length; i++) {if(!callback(this[i],i,this)){//判定不满足的情况return false; //一旦有一个不满足,那么我们就直接返回false,不再执行接下来的代码}}return true;//当所有的元素都不返回false,那么咱们就返回true
}


Array.some()
------------Array.some() 方法跟 Array.every() 方法刚好相反;它也是返回出来一个 boolean 值,不同的是只要有数组里有一个元素满足判定条件,那么就会直接返回 true;若没有一个满足条件,那么就会返回 false。根据这些条件我们就可以往这个方向思考:1.对数组每一项进行条件判断,只有一个满足,直接 return true2.循环结束后加一个 return false 用于返回当所有情况都不满足了,那么返回 false```
Array.prototype.my_every = function(callback) {for(let i = 0 ; i < this.length; i++) {if(callback(this[i],i,this)){//判定满足的情况return true; //一旦有一个满足,那么我们就直接返回true,不再执行接下来的代码}}return false;//当所有的元素都不返回true,那么咱们就返回false
} 

Array.reduce()

Array.reduce() 方法应该算是数组的所有的遍历方法里面比较特殊的一个方法吧;

它接收两个参数,第一个参数是需要执行的回调函数,而第二个参数则是初始的一个变量值;

这么说它的第二个参数可能大家都不太理解,没关系,待会儿会带大家仔细讲解。

再讲它的回调函数,它的回调接收四个参数:

function myFunction(pre, value, index, array) {return pre + value;
}
//四个参数分别代表着:
//- 总数(初始值/先前返回的值)
//- 项目值
//- 项目索引
//- 数组本身 

那么咱们来看一看官方给出的 Array.reduce() 的实例吧:

let arr = [1,2,3,4,5,6];const res = arr.reduce((pre, value, index, array)=>{console.log(pre,value,index,array);return pre + value
},0)console.log(res);// 运行结果:
// 0 1 0 [ 1, 2, 3, 4, 5, 6 ]
// 1 2 1 [ 1, 2, 3, 4, 5, 6 ]
// 3 3 2 [ 1, 2, 3, 4, 5, 6 ]
// 6 4 3 [ 1, 2, 3, 4, 5, 6 ]
// 10 5 4 [ 1, 2, 3, 4, 5, 6 ]
// 15 6 5 [ 1, 2, 3, 4, 5, 6 ]
// 21 

我们可以看到的就是第一次 pre 的值就是我们 reduce 所接收到的第二个参数,而之后的 pre 都是上一次 pre 与 value 的和;

那么为什么是 pre 和 value 的和呢?

原因是每次 reduce 都在执行那个回调,而回填返回出来的值都会传到下一次 reduce 遍历的 pre 中;

这就是 reduce 所接收的各个参数了。

reduce 这个方法多用于数组的累加,累乘等等累积值。

那么如果不给 reduce 传第二个参数会怎样?

这是个好问题,咱们来一起看看:

可以看到的是,它的打印少了一层,那就是第一层,它从数组的第二项开始遍历,而第一个 pre 则是数组没有被遍历的第一项。

所以由此可知,如果我们不给 reduce 传第二个参数,那么它就会默认从数组第二项开始遍历,而第一个 pre 则会变成数组第一项。

那么要手写 reduce 这个方法,我们需要做到哪些条件呢?

1.判断 reduce 是否有接收到第二个参数,做情况判断,决定开始从数组哪个位置开始遍历;2.把每一次回调 return 出来的值都传给下一次回调的 pre ;3.把回调里最后一次 return 传出去。有了这个方向咱们就可以开始手写了:

Array.prototype.my_reduce = function(callback, ...args) {let pre, start = 0;// 定义一个 pre ,方便把最后一次 pre 传出去;if (args.length) {// 判断是否存在第二个参数,决定数组从下标0,还是下标1开始遍历,同时给第一次 pre 赋值pre = args[0]} else {pre = this[0]start = 1}for (let i = start; i < this.length; i++) { // 遍历调用回调,把每一次 pre 传到下一次pre = callback(pre, this[i], i, this)}return pre// 把最后的 pre 传出去} 

那么最后的 Array.reduce() 也写完了,数组的遍历方法手写也就到此为止啦。

最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

相关文章:

数组中的各种迭代API方法手写

js的数组上有很多实用的方法&#xff0c;不论是在遍历数组上&#xff0c;还是在操作数组内元素上&#xff0c;它有许多不同的遍历数组的方法&#xff0c;同时它还有着可以直接操作数组中间元素的方法。 接下来&#xff0c;我来带大家手写数组里的 遍历方法 。 Array.forEach(…...

详解量子计算:相位反冲与相位反转

前言 本文需要对量子计算有一定的了解。需要的请翻阅我的量子专栏&#xff0c;这里不再涉及基础知识的科普。 量子相位反冲是什么&#xff1f; 相位反转&#xff08;phase kickback&#xff09;是量子计算中的一种现象&#xff0c;通常在量子算法中使用&#xff0c;例如量子…...

C++——C++11第三篇

目录 包装器 function包装器 bind 包装器 function包装器 function包装器 也叫作适配器。C中的function本质是一个类模板&#xff0c;也是一个包装器。 上面的程序验证&#xff0c;我们会发现useF函数模板实例化了三份。 包装器可以很好的解决上面的问题 &#xff0c;让它只实…...

180 2 22222

选择题(共180题,合计180.0分) 1. 在项目开工会议期间&#xff0c;项目发起人告诉产品负责人和团队项目章程即将完成。然而&#xff0c;由于存在在紧迫的期限内满足政府监管要求的压力&#xff0c;发起人希望立即开始工作。产品负责人下一步应该做什么&#xff1f; A 告诉发起人…...

成人高考初中毕业能报名吗 需要什么条件

初中学历的人员不能直接报名成人高考&#xff0c;考生需要有普通高中&#xff0c;职业高中&#xff0c;中专毕业证等高中同等学力就可以进行报名&#xff0c;在报名期间登陆所在省的教育考试院的成人高考报名入口进行报考。成人高考报名条件是什么1、遵守宪法和法律。2、国家承…...

ChatGPT初体验

ChatGPT初体验 前言 嘿嘿&#xff0c;最近啊AI ChatGPT刷新各大网站&#xff0c;对于我们国人而将很不友好&#xff0c;真的太不友好了。我呢在去年open AI发布的时候就有所关注&#xff0c;那个时候还没有像现在这样火热。谁知道短短几个月便传遍大街小巷。 一、什么是chatG…...

ChatGPT概念狂飙!究竟魅力何在?

原文&#xff1a;http://www.btcwbo.com/6988.html 近期&#xff0c;ChatGPT引领的人工智能概念在资本市场一路狂飙&#xff0c;AIGC题材持续发酵。截至2月7日&#xff0c;Wind ChatGPT指数今年以来累计上涨超50%&#xff0c;汉王科技、海天瑞声、云从科技等概念股股价已经翻倍…...

如何下载阅读Spring源码-全过程详解

这篇文章记录了下载spring源码和在IDEA中打开运行的全过程&#xff0c;并且记录了过程中遇到的问题和解决方案&#xff0c;适合需要学习spring源码的同学阅读。 1.spring源码下载地址 通过Git下载spring-framework项目源码&#xff1a; git clone https://github.com/spring…...

学了两个月的Java,最后自己什么也不会,该怎么办?

学着学着你会发现每天的知识都在更新&#xff0c;也都在遗忘&#xff0c;可能就放弃了。但是只要自己肯练&#xff0c;肯敲代码&#xff0c;学过的知识是很容易就被捡起来的。等你学透了用不了一年也可以学好 Java的运行原理&#xff1a;Java是一门编译解释型语言&#xff0c;…...

前端vue实现获取七天时间和星期几功能

前端vue实现获取七天时间和星期几功能 功能展示代码 <div v-for"(item,index) in same_week" :class"[same_dayitem.date? activ :,dis]" click"select(item)" :keyindex><span>{{item.name}}</span><span>{{item.…...

zookeeper单机部署

一.下载zookeeper压缩包 二.上传解压安装包到/data/zookeeper目录&#xff0c;并解压 tar -zxvf apache-zookeeper-3.5.8-bin.tar.gz 三.修改配置文件 cd apache-zookeeper-3.5.10-bin/conf mv zoo_sample.cfg zoo.cfg vi zoo.cfg 修改为如下&#xff1a; dataDir/data/zooke…...

单片机输入输出模式

单片机输入输出模式输入模式模拟输入、浮空输入、上拉输入、下拉输入GPIO输出模式推挽输出、开漏输出、复用推挽输出、复用开漏输出。上下拉电阻上拉电阻下拉电阻输入模式 模拟输入、浮空输入、上拉输入、下拉输入 模拟输入&#xff1a;I/O端口的模拟信号&#xff08;电压信号…...

数据结构_ 堆结构与堆排序(c++ 实现 + 完整代码 )

堆结构与堆排序 文章目录堆结构与堆排序引入堆堆结构所满足的数学特性准备代码----------- 往堆中插入元素----------- 删除堆顶堆排序构建完整代码及测试动态分配版本非动态版本引入堆 二叉树 具有左孩子与右孩子的最普通的二叉树。 满二叉树 特殊的二叉树&#xff1a;每个节…...

【MySQL】sql中explain解释和应用

这里写目录标题学习原因MySQL中explain的使用和用法解释explain的使用explain 运行结果的意义文字展示表格展示参考资料&#xff1a;结束语学习原因 在对sql的优化过程中使用了explain对指定的sql进行查看它的运行效果&#xff0c;以便找出sql的性能特点并进行优化 MySQL中ex…...

从零实现深度学习框架:Seq2Seq从理论到实战【实战篇】

来源&#xff1a;投稿 作者&#xff1a;175 编辑&#xff1a;学姐 往期内容&#xff1a; 从零实现深度学习框架1&#xff1a;RNN从理论到实战&#xff08;理论篇&#xff09; 从零实现深度学习框架2&#xff1a;RNN从理论到实战&#xff08;实战篇&#xff09; 从零实现深度…...

【数据结构入门】-链表之单链表(1)

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【数据结构初阶&#xff08;C实现&#xff09;】 文章标题回顾链表链表的概念及结构各种节点打印链表尾插创建节点尾删头插头删查找在pos…...

Docker竟如此简单!

文章目录什么是容器&#xff1f;容器隔离何为“边界”&#xff1f;容器和虚拟机一样吗&#xff1f;基于 Linux Namespace 隔离机制的弊端容器限制何为“限制”&#xff1f;Cgroups 对资源的限制能力缺陷单进程模型容器镜像容器的诞生容器的一致性何为“层&#xff08;layer&…...

在外包干了几年,感觉自己都快费了

先说一下自己的情况。大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近2年的点点点&#xff0c;今年年上旬&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经在一个企业干了五年的功能测试…...

Java实现多线程有几种方式(满分回答)

目录JDK8 创建的线程的两种方式orcle文档解释方式一&#xff1a;继承Thread类方式二&#xff1a;实现Runnable接口同时用两种的情况其他间接创建方式Callable接口线程池JDK8 创建的线程的两种方式 orcle文档解释 orcle文档&#xff1a;https://docs.oracle.com/javase/8/docs…...

实例4:树莓派GPIO控制舵机转动

实例4&#xff1a;树莓派GPIO控制舵机转动 实验目的 通过背景知识学习&#xff0c;了解舵机的外观及基本运动方式。了解四足机器人mini pupper腿部单个舵机的组成结构。通过GPIO对舵机进行转动控制&#xff0c;熟悉PWM。了解mini pupper舵机组的整体调零。 实验要求 使用Py…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...