JavaScript数组的迭代方法map,filter,reduce,some,every,forEach详解

数组对象map,filter,reduce,some,every方法详解

0. 前言

最近在前端笔试上数组的这几个方法上栽了几个跟头,缘于对这几个方法没有深入的了解,只知道其常规用法,没有顾虑到一些方法使用上的细节,在这里做个总结,复习的同时做个记录,方便以后查阅。

以上所有的数组迭代方法都来自于 ECMAScript5 对数组新增的操作方法,而不是 ECMAScript 6 新定义的方法。

参考资料:
《Javascript高级程序设计》
MDN: https://developer.mozilla.org/zh-CN/
菜鸟教程:http://www.runoob.com/

1. map() 方法

1.1 map() 方法常规使用

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
数组执行完map() 方法后返回一个新的数组,原数组元素不会发生改变。

var array1 = [1, 4, 9, 16];

const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

console.log(array1)
// expected output: Array [1, 4, 9, 16]

map() 方法不会对空数组进行检测, 结果仍然返回一个空数组,console.log(‘123’) 不会被执行。

var array1 = [];

const map1 = array1.map(x => {console.log('123')});

console.log(map1);
// expected output: Array []

如果 map() 方法不对元素进行操作且不指定返回值的话,新数组每个元素会返回 undefined 值

var array1 = [1,2,3];

const map1 = array1.map((item, index, arr) => {console.log('123')});
// expected output: 
// 123
// 123
// 123
console.log(map1);
// expected output: Array [ undefined, undefined, undefined ]

1.2 map() 方法中的参数说明

array.map(function(currentValue,index,arr),thisValue)方法一共可以传入两个参数。

第一个参数为一个函数 function(currentValue, index,arr),该函数中又包含了三个参数:

currentValue:表示的是当前元素的值。必须值。
index:当前元素的索引(从0开始)。可选值。
arr:当前元素属于的数组对象。也就是执行 map 方法的原数组对象。可选值。

var array1 = [1,2,3];

const map1 = array1.map((item, index, arr) => {console.log(item +':'+ index +':'+ arr)});

// expected output: 
//1:0:1,2,3
//2:1:1,2,3
//3:2:1,2,3

第二个参数 thisValue 为可选。对象作为该执行回调时使用,传递给函数,用作 “this” 的值。
如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。

var array1 = [1,2,3];

var obj = {
	mykey : 1000
}
var mykey = 2000 

const map1 = array1.map(x => x + this.mykey);

console.log(map1)// (3) [2001, 2002, 2003]

该参数对箭头函数无效,箭头函数没有 this 对象,所以无法改变 this 指向

const map1 = array1.map(x => x + this.mykey, obj);
console.log(map1) //(3) [2001, 2002, 2003]

使用普通函数的结果

var array1 = [1,2,3];

var obj = {
	mykey : 1000
}
var mykey = 2000 

const map1 = array1.map(function(x){
	return x + this.mykey
},obj);

console.log(map1) //(3) [1001, 1002, 1003]

1.3 map() 方法陷阱题

const map1 = [1,2,3].map(parseInt)
console.log(map1)
// (3) [1, NaN, NaN]

该题与函数传入的参数有关,详解见 https://www.cnblogs.com/Candybunny/p/5627905.html

2. filter() 方法

2.1 常规用法

filter() 方法返回一个新的数组,新的数组包含所有在函数中结果为 true 的元素,原数组不会改变。

var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length > 6); // 返回值为true的所有结果都会加入新数组

console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]

2.2 参数说明

array.filter(function(currentValue,index,arr), thisValue)
filter 参数的用法与 map 方法一致,不再重复描述。

3. reduce() 方法

3.1 reduce 方法的定义与常规用法

reduce() 方法对数组中的每个元素执行一个由用户提供的 reducer 函数,将其结果汇总为单个返回值。

const array1 = [1, 2, 3, 4];

const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

3.2 reduce 方法的参数说明

语法: array.reduce(function(accumulator, currentValue, currentIndex, arr), initialValue)
reduce() 方法传入两个参数:
第一个参数为一个函数。必须值

  • 第一个参数传入的函数有 4 个参数:
  • 1.accumulator 必需。初始值, 或者计算结束后的返回值。
  • 2.currentValue 必需。当前元素的值。
  • 3.currentIndex 可选。当前元素的索引,元素索引从 1 开始!
  • 4.arr 可选。当前元素所属的数组对象。
const array1 = [1, 2, 3, 4];

const reducer = (accumulator, currentValue, index) => {
	console.log('执行了第'+index+'次,accumulator='+accumulator+' currentValue=',currentValue)
	return 'a'
};

let ret = array1.reduce(reducer)// "a"

// index 索引从 1 开始
// Output:
// 执行了第1次,accumulator=1 currentValue= 2
// 执行了第2次,accumulator=a currentValue= 3
// 执行了第3次,accumulator=a currentValue= 4

由上述代码可知,数组遍历中每一次的accumulator的值,均为上一次遍历中返回的结果。而accumulator的初始的值已经被固定,是数组的第一个元素。而最终返回的结果也是最后一次遍历中返回的值。例如这里就是返回一个“a”。

如果数组只有一个元素,reducer 不会被执行,reduce 方法直接返回数组的第一个元素

const array1 = [1];

const reducer = (accumulator, currentValue, index) => {
	console.log('执行了第'+index+'次,accumulator='+accumulator+'currentValue=',currentValue)
	return 9
};

let ret = array1.reduce(reducer)
console.log(ret) // Output: 1

如果reduce函数中没有返回任何值,且数组的长度大于1,则返回undefined

const array1 = [1,2,3];

const reducer = (accumulator, currentValue, index) => {
	console.log('gg')
};

let ret = array1.reduce(reducer)
console.log(ret) // Output: undefined

如果数组为空则直接报错,提示数组没有初始值(首元素),也就是无法为 accumulator 赋予初值。

const array1 = [];

const reducer = (accumulator, currentValue, index) => {
	return 1
};

let ret = array1.reduce(reducer)
// Uncaught TypeError: Reduce of empty array with no initial value

快速求数组总和

const array1 = [1, 2, 3, 4];

const reducer = (accumulator, currentValue, index) => {
	console.log('acc='+accumulator+' cur='+currentValue)
	return accumulator + currentValue
};

let ret = array1.reduce(reducer)
console.log(ret)

// acc=1 cur=2
// acc=3 cur=3
// acc=6 cur=4
// 10

第二个参数为一个初始值 initValue。可选值。
reduce 方法在有第二个参数 initValue 的情况下,此时传入的 initValue 就充当了原来数组中的首元素的作用,初始的 accumulator 值被赋予为 initValue, 而不是数组的首元素,如果此时数组为空,也不会报错,会直接返回 initValue 的值。同时数组的 index 序号从 0 开始,数组的第一个元素也参与 reduce 计算。迭代执行的总次数为数组的元素个数。

const array1 = [1, 2, 3, 4];

const reducer = (accumulator, currentValue, index) => {
	console.log('acc='+accumulator+' cur='+currentValue+' index='+index)
	return accumulator + currentValue
};

let ret = array1.reduce(reducer, 5)
console.log(ret)

// acc=5 cur=1 index=0
// acc=6 cur=2 index=1
// acc=8 cur=3 index=2
// acc=11 cur=4 index=3
// 15

3.3 reduce 方法的构造(自定义函数实现数组 reduce 方法)

自己封装的,可能写的不是很好,大概是这么个意思,相比于原来的 reduce 不同之处在于数组为空的时候不再报错,返回一个 null。

Array.prototype.myreduce = function(func, initValue){
   if(!this[0]){
   	return null
   }
   let begin = 0
   let accumulator = 0
   if(initValue){
   	accumulator = initValue
   } else {
   	accumulator = this[0]
   	begin = 1
   }
   for(let i = begin; i < this.length; i++){
   	accumulator = func(accumulator, this[i], i, this)
   }
   return accumulator
}
let reducer = (acc, cur)=>acc+cur
console.log([1,2,3,4].myreduce(reducer,5))
// Output: 15

4. some() 方法和 every() 方法

4.1 定义与常规用法

some() 和 every() 方法都不会对空数组进行检测。
some() 和 every() 方法不会改变原始数组。
它们的返回值都为 true 或者 false
every() 是对数组中每一项运行给定函数,如果该函数对每一项返回true, 则返回true。
some() 是对数组中每一项运行给定函数,如果该函数对任一项返回true, 则返回true。

[1,2,3,4,5].some(x=>x >= 5) // true

[1,2,3,4,5].every(x=>x >= 5) //false

4.2 参数说明

array.every(function(currentValue,index,arr),thisValue)
array.some(function(currentValue,index,arr),thisValue)
它们的参数描述和用法与 map() 方法一致, 具体可以参考 map() 方法, 这里不再重复描述。

5. forEach() 方法

5.1 定义与用法

forEach() 方法对数组的每个元素执行一次提供的函数。

var array1 = ['a', 'b', 'c'];

array1.forEach(function(element) {
  console.log(element);
});

// expected output: "a"
// expected output: "b"
// expected output: "c"

forEach() 方法没有返回值,或者说返回值为 undefined

var array1 = [1, 2, 3];
var ret = array1.forEach( x => x*2 )
console.log(ret) // undefined

5.2 参数说明

array.forEach(function(currentValue, index, arr), thisValue)
第一个参数 function(currentValue, index, arr): 传入一个函数,该函数有三个参数:

  • 第一个函数参数: currentValue 为当前元素值
  • 第二个函数参数:当前元素索引值,从0开始
  • 第三个函数参数:原数组对象

第二个参数thisValue :当执行回调函数时用作 this 的值(参考对象)。如果这个参数为空, “undefined” 会传递给 “this” 值

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值