JavaScript--ES5数组新增方法(forEach、filter、every、some、reduce、reduceRight)的用法与原码实现

本文主要是介绍JavaScript--ES5数组新增方法(forEach、filter、every、some、reduce、reduceRight)的用法与原码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ES5数组方法(forEach、filter、every、some、map、reduce、reduceRight)的用法

在讲原码实现之前,先将各个API的用法。这里我先放一个数组,以便后续使用~~
<script>var dataArr = [{name: "John", des: '全网最帅', sex: 'boy', age: 18, grade: 80},{name: "sunny", des: '比刘宝宝丑那么点', sex: 'boy', age: 30, grade: 100},{name: "MrDeng", des: '比成哥丑那么点', sex: 'boy', age: 45, grade: 100},{name: "cst", des: '全网最丑', sex: 'boy', age: 26, grade: 100},{name: "chang", des: '全网最矮', sex: 'girl', age: 18, grade: 80},{name: "Monikatx", des: '全网最美', sex: 'girl', age: 20, grade: 100},];
</script>

1.forEach

    dataArr.forEach(function (item, index, self){this[index].innerText = item.name;}, dom);

点击这里(forEach详细API)

forEach必须要传一个匿名函数作为实参,第二个参数是可选参数,讲用作改变匿名函数的this。
forEach的作用,可以看做是加强的for循环,用来遍历数组
forEach之所以是看做是加强版的for循环,就是因为他也是一个循环。所发挥的作用也for相差无几,底层也是利用的for循环。那他到底是怎么循环的呢?遍历数组length长度多长,这里的第一个实参,匿名函数就执行几次,而形参也会跟着被遍历。

这里我先说下匿名函数形参(形参是可以随意命名的,可以选择自己喜欢的名字):

    形参一: item  代表的所遍历数组的value值, 如:arr[0] = "刘宝宝" ,"刘宝宝"是value值。形参二: index 代表的所遍历数组的key值(索引), 如:arr[0] = "刘宝宝" ,[0]是key值。形参二: self 代表的所遍历数组自己, 如:arr[0] = "刘宝宝" ,arr是self值。

forEach传的匿名函数会自己调用,而第二个实参,将被作为匿名函数的this传入 ,如:

这里写图片描述
之后6个方法原理是一样的,之后我就不在重复述说了

2.filter

  // filtervar younger = dataArr.filter(function (item, index, self){let flag = item.age < 25;this[index].innerText += ( flag  ?  " baby" : " old");return flag;}, dom)console.log(younger);//输出[{name: "John"...}, {name: "chang"}, {name: "Monikatx"}]

filter与forEach 传参相同,必须要传一个匿名函数作为实参,可选择传一个值作为this。匿名函数的形参也与forEach 的匿名函数相同。请参考forEach 。

这里主要说说filter的功能:执行完成返回一个数组,我这里用younger接收。执行匿名函数内的代码时,返回一个boolean值判断真假,若不是布尔值返回给filter,filter自己将做隐式转化为布尔值判断真假。当返回值return 为真(true),将该次遍历的数组添加到younger。反之false舍弃,不添加。

3.every

 // every 当遇上false停止遍历var flagEvery = dataArr.every(function (item, index, self){console.log(item.grade);return item.grade > 90 ? true : false;}, dom)console.log(flagEvery);

every与forEach 传参相同,必须要传一个匿名函数作为实参,可选择传一个值作为this。匿名函数的形参也与forEach 的匿名函数相同。请参考forEach 。

every的功能:执行完成返回一个布尔值。执行匿名函数内的代码时,返回一个boolean值判断真假,若不是布尔值返回给every。当所有返回值return 为真,返回真(true),只要有一个不为真(true)返回假(false)。

4.some

// some 遇上true停止遍历
var flagSome = dataArr.some(function (item, index, self){console.log(item.grade);return item.grade > 90 ? true : false;
}, dom)
console.log(flagSome);

some与forEach 传参相同,必须要传一个匿名函数作为实参,可选择传一个值作为this。匿名函数的形参也与forEach 的匿名函数相同。请参考forEach 。

some的功能:执行完成返回一个布尔值。执行匿名函数内的代码时,返回一个boolean值判断真假,若不是布尔值返回给some。当所有返回值return 有一个为真(true),返回true,全为假(false)返回假(false)。

5.map

// map 映射
var newAge = dataArr.map(function (item, index, self){// return item.age + 10;item.age += 10;return item;
}, dom)
console.log(newAge);

map与forEach 传参相同,必须要传一个匿名函数作为实参,可选择传一个值作为this。匿名函数的形参也与forEach 的匿名函数相同。请参考forEach 。

map的功能:执行完成返回一个新的数组。执行匿名函数内的代码时,将该次遍历的返回值添加到新数组中。这段代码中我写了两段return,第一段return改变的是对象里的属性,并返回该属性值,这里返回的是原始值,和之前的的数组将没有联系。第二段return改变的也是对象里的属性,但返回的是对象本身,对象是引用值。如果你对新数组里的对象进行操作,原素组里的对象也将发生改变

6.reduce

// reduce
var allName = dataArr.reduce(function (prev, current, index, self) {return prev + current.name;
}, '+');
console.log(allName)

reduce这里需要注意,和forEach有点传参有些不一样了,第一个实参也是匿名函数,自行调用。这第二个实参也是可选参数,可传可不传,但是作用不一样。forEach是传一个实参作为this,而reduce的第二个实参是初始值。具体看下面~~

reduce的匿名函数形参:

  1. 形参一: prev 代表的所遍历数组索引位的上一个索引位匿名函数的返回值。若当前索引位为0,先看reduce有没有第二实参,也就是我上面所说的初始值。有,将初始值给prev。无,prev为空。
  2. 形参二: current 代表的所遍历数组的value值, 如:arr[0] = “刘宝宝” ,”刘宝宝”是value值。
  3. 形参三: index 代表的所遍历数组的key值(索引), 如:arr[0] = “刘宝宝” ,[0]是key值。
  4. 形参四: self 代表的所遍历数组自己, 如:arr[0] = “刘宝宝” ,arr是self值。

reduce的功能:执行完成返回一个返回值。执行匿名函数内的代码时,执行匿名函数内的代码块。返回一个返回值,但这个返回值不是给reduce自己用的,而是给自己下一个遍历数组索引位下一个匿名函数形参prev赋值的。最后一个索引位匿名函数的返回值才是reduce的返回值。

7.reduceRight

// reduceRightvar allNameBack = dataArr.reduceRight(function (prev, current, index, self) {return prev + current.name;}, '-')console.log(allNameBack)

reduceRight与reduce其实差不多,区别在于他的遍历顺序是反过来的。细节没什么好说的,不懂的可以参考reduce

reduceRight的功能:执行完成返回一个返回值。执行匿名函数内的代码时,执行匿名函数内的代码块。返回一个返回值。reduceRight遍历是从数组最后一位开始遍历,初始也是给的最后数组索引位匿名函数的形参prev。返回值是索引位 [0] 匿名函数的返回值。


好了,本文到此就结束了~~
期待下一次更新吧!!

好吧,我是真想睡了。写到这已经是将近凌晨4点半了。但我还是坚持写完,整篇没看到我皮,是不是不适应??不是不想皮,是实在太困了。

接下来是用js原码自己封装7种ES5数组方法——–


ES5数组方法(forEach、filter、every、some、map、reduce、reduceRight)的原码实现

1.myForEach

Array.prototype.myForEach = function (fn) {var i, _self = this, len = _self.length, target = arguments[1];for(i = 0; i < len; i++) {fn.apply(target, [_self[i], i, _self]);}
}

既然是数组方法,那就要封装在Array.prototype上。Array.prototype.myForEach = function () {fn},这里的函数表达式执行就是arr.myForEach ()。按道理这么基础的东西,我本不应该再讲,但考虑到,我同学在听课的时候已经被绕晕了,所以是讲一下。这里的 fn 是形参,那执行就是arr.myForEach (function () {}), fn 就是这个里面的实参(匿名函数了)。可能你们会有疑惑,那dom作为第二个实参,在这怎么没看到与之对应的形参呢?我只看到一个形参!!!来来,接下来给你看一下第二个形参在哪里。不应该叫形参了,得叫实参列表这里写图片描述

这里通过argument[1]来获取第二个实参,也就是dom。而之前说的foreach第二个实参将成为匿名函数的this,就是在这了apply将匿名函数fn的this指向dom,并传入三个形参,变量名i, _self, len, 分别是指遍历的索引,被遍历的数组本身也就是arr, len是数组的长度arr.length,而这里面的for相信你们也能看懂,让匿名函数fn执行len-1次。希望你们不要再被 myForEachfn 给绕晕,我已经尽我最大的能力来讲了。下面的我就不再这么讲了

2.myFilter

 // 封装myFilter
Array.prototype.myFilter = function (fn) {var i, _self = this, len = _self.length, target = arguments[1], newArr = [];for(i = 0; i < len; i++) {fn.apply(target, [_self[i], i, _self]) ? newArr.push(_self[i]) : '像刘宝宝这么帅的人不多了';}return newArr;
}

有没有发现myFilter 和myForEach长竟然如此相像,先不要惊讶,因为在后面你会发现,这7个方法都长的差不多。

这里myFilter 比myForEach多了一个newArr数组,和一个return。这是因为filter是有返回值的,这个返回值也得是一个数组。之前说过filter每次遍历的匿名函数fn都会返回一个值给filter判断,这里for循环内fn.apply就是一次执行,执行后的返回值用作三目运算符判断,返回值为true,newArr添加当前数组索引位_self[i]。
然而这里后面这串字符串才是本文的重点。来来,圈起来,这是重点考试肯定是要考的。
emm,既然是筛选,那么为false就不要它执行任何操作就好了,但是三目运算符是你fasle也要有个表达式,那我就填个空就好了,但是这样不能表现出我的文笔功底,才会引出这么有哲学的一句话。令人反思啊。。。
最后遍历完了,就要返回数组,return newArrr。

3.myEvery

// 封装myEveryArray.prototype.myEvery = function (fn) {var i, _self = this, len = _self.length, target = arguments[1], flag = true;for(i = 0; i < len; i++) {if(!fn.apply(target, [_self[i], i, _self])){flag = false;break;} }return flag;}

是的,我是个诚实的宝宝。你看是不是长得相差不大?

myEvery返回的是true或false。所以开头声明一个flag=true,接下来我只需要遍历出匿名函数fn不是true,让flag=false就好了,当然既然只要是有一个不为true,every就要返回false,那你匿名函数fn返回给我false。我干脆就不遍历了,让你出去吧。免得还让我做无用功,break退出块级作用域,块级作用域不知道的我这里也不说了。最后返回flag为false,当然你匿名函数给我的返回值全是true,那我根本没走if里,自然flag就是true了。

4.mySome

// 封装mySome
Array.prototype.mySome = function (fn) {var i, _self = this, len = _self.length, target = arguments[1], flag = false;for(i = 0; i < len; i++) {if(fn.apply(target, [_self[i], i, _self])){flag = true;break;} }return flag;
}

这一块呢,我就不讲了。你只要看懂上面的,下面的你一定能看懂。

mySome返回布尔值。是的,就这么简短~~不服?不服你来打我啊!!

5.myMap

// 封装myMapArray.prototype.myMap = function (fn) {var i, _self = this, len = _self.length, target = arguments[1], newArr = [];for(i = 0; i < len; i++) {newArr.push(fn.apply(target, [_self[i], i, _self]));// 这里可以使用深度克隆,让返回值是引用值也区分开来}return newArr;}

myMap也没什么好讲的,就是声明一个数组,匿名函数操作完添加,返回数组。

myMap返回数组。是的,还是就这么简短~~不服?不服你又能怎样呢!!

6.myReduce

// 封装myReduce
Array.prototype.myReduce = function (fn) {var i, _self = this, len = _self.length, initValue = arguments[1];for(i = 0; i < len; i++) {initValue = fn(initValue, _self[i], i, _self);}return initValue;
}

myReduce也没什么好讲的。。。。。。但是我的求生欲告诉我这里还是要讲的。

myReduce的实参列表arguments[1]第二个实参不再是改变匿名函数(fn) this指向,而是直接作为匿名函数fn的第一个实参传入,传进去干嘛呢?之前说了reduce索引位是0的时候,他是没有上一返回值的,所以讲第二个实参传入作为初始值,也就是索引位是0的的上一个返回值。 initValue = fn(initValue, _self[i], i, _self);这样写是让初始值initValue(也就是当前索引返回值)赋值为下一个索引位的匿名函数fn使用(prev)。到for循环遍历完initValue也就被赋值成最后一位索引匿名函数fn的返回值;

6.myReduceRight

 // 封装myReduceRight
Array.prototype.myReduceRight = function (fn) {var i, _self = this, len = _self.length, initValue = arguments[1];for(i = len-1; i >= 0; i--) {console.log(i)initValue = fn(initValue, _self[i], i, _self);}return initValue;
}

myReduceRight也讲讲吧。

myReduceRight是反序遍历,那for循环也就要反向遍历,for(i = len-1; i >= 0; i–)。
好了,讲完了~~


最后,本文到这里就结束了。首先,有疑惑或者我哪里讲的不对,麻烦大家指正,我写文章纯属是来了兴趣就写上一篇,担心给大家带来误导。其次,感谢大家的支持,上次文章的阅读量给了我很大的激励,两天就200多阅读量,这使我膨胀了,我膨胀到自己都不认识了,我要飞上天和太阳肩并肩~~

这篇关于JavaScript--ES5数组新增方法(forEach、filter、every、some、reduce、reduceRight)的用法与原码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/276161

相关文章

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

mysql中insert into的基本用法和一些示例

《mysql中insertinto的基本用法和一些示例》INSERTINTO用于向MySQL表插入新行,支持单行/多行及部分列插入,下面给大家介绍mysql中insertinto的基本用法和一些示例... 目录基本语法插入单行数据插入多行数据插入部分列的数据插入默认值注意事项在mysql中,INSERT I

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热