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

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows