提出问题
现在有一个需求:给一个数字数组,我们要对其进行一些操作
首先,将所有小于60的数取出来,然后将这些数都乘以2,最后将乘以2后的数全部加起来,最后打印加起来的值
其实这个需求挺简单的,无非就是几个循环,创建几个新数组保存一下,然后进行累加打印就行了。
好,既然提出了解决方法,那么直接撸代码
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
let arr1 = []
let arr2 = []
let sum = 0
// 这个循环把所有小于60的数放进了arr1数组
for (let i = 0; i < arr.length; i++) {
if (arr[i] <= 60) {
arr1.push(arr[i])
}
}
console.log(arr1)
// 这个循环把arr1数组的所有数全部乘以2并放进arr2数组
for (let i = 0; i < arr1.length; i++) {
arr2.push(arr1[i] * 2)
}
console.log(arr2)
// 这里一个循环求总和
for (let i = 0; i < arr2.length; i++) {
sum += arr2[i]
}
console.log(sum)
提出优化
看!需求完成了
但有人突然提出:“我可以使用for of对其进行优化!”
那就满足一下他,上代码
// 刚刚全部使用的for循环,有人提出,可以使用for of进行优化,确实,让我们来看看
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
let arr1 = []
let arr2 = []
let sum = 0
// 这个循环把所有小于60的数放进了arr1数组
for (let i of arr) {
if (i <= 60) {
arr1.push(i)
}
}
console.log(arr1)
// 这个循环把arr1数组的所有数全部乘以2并放进arr2数组
for (let i of arr1) {
arr2.push(i * 2)
}
console.log(arr2)
// 这里一个循环求总和
for (let i of arr2) {
sum += i
}
console.log(sum)
// 其实没多大变化
进一步优化
然而,for…of方法的优化效果好像不尽人意,同样还是三个循环和创建两个新数组,只是稍微减少了arr1[i]这类的操作
这时候 ES6说话了:“用我新增的数组方法它不香吗?”
好家伙,既然你这么说了,那就用你了
// 这里我们就可以使用es6新增的数组方法,我们先看看他有多神奇
// 也可以看看函数式编程是有多爽
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
let sum = arr.filter(function (n) {
return n <= 60
}).map(function (n) {
return n * 2
}).reduce(function (pervValue, n) {
return pervValue + n
})
console.log(sum)
// 这样就打印出了正确答案,先不急,我会一步一步来介绍这些数组方法
在使用了ES6的filter、map、reduce后,我们得到了正确结果的同时还减少了创建新数组的操作,
但这三个方法都是什么呢?让我一一介绍
filter()
filter 过滤器的意思,功能也跟过滤器一样
参数:filter 接收一个函数,function(currentValue,index,arr)
其函数接收三个参数:
currentValue 必须。当前元素的值
index 可选。当前元素的索引值
arr 可选。当前元素属于的数组对象
返回值:返回一个新数组,也就是在参数的函数中返回true的数
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
// 第一个参数必选,当前的值
// 第二个参数可选 当前元素索引值
// 第三个参数可选 当前元素属于的数组对象
let arr1 = arr.filter(function (currentValue, index, arr) {
return currentValue <= 60 //我们只需要第一个参数,进行判断,filter会将内部函数返回为true的值作为返回值给一个新数组
})
console.log(arr1)
map()
map方法
参数:map 接收一个参数 function(currentValue,index,arr)
函数的接收三个参数:
currentValue 必须。当前元素的值
index 可选。当前元素的索引值
arr可选。当前元素属于的数组对象
返回值:返回一个新数组,也就是在参数的函数中进行操作过后的值
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
// 第一个参数必选,当前的值
// 第二个参数可选 当前元素索引值
// 第三个参数可选 当前元素属于的数组对象
let arr1 = arr.map(function (currentValue, index, arr) {
return currentValue * 2 //同样,我们只需要第一个参数,map会将经过内部函数操作后的值作为返回值给一个新数组,这里就是把arr中所有值乘以2给arr1
})
console.log(arr1)
reduce()
reduce 最复杂的方法
参数:filter接收两个参数
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
第一个参数:是一个函数
第二个参数:initalValue 就是最开始初始值
其函数接收四个参数:
total 必需。初始值, 或者计算结束后的返回值。
currentValue 必需。当前元素
currentIndex 可选。当前元素的索引
arr 可选。当前元素所属的数组对象。
reduce通常用来完成对数组值进行同一种操作的时候,就像现在的累加
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
// 第一个参数 必选 每次累加得到的值 也就是这次的total 是上次的total+currentValue的和
// 第二个参数 必选 当前元素的值
// 第三个参数 可选 当前元素的索引
// 第四个参数 可选 当前元素所属的数组对象
let sum = arr.reduce(function (total, currentValue, currentIndex, arr) {
return total + currentValue //这里我们只用到了第一和第二个参数完成累加, 注意:第一次累加用的是initalValue 作为total
}, 0)
console.log(sum)
这里可能很难看懂,来分析几次累加就好了:
第一次 total +currentValue时,这里的total其实就是reduce的第二个参数initalValue,这里initalValue为0,也就是0加上currentValue,这时候currentValue的值为30, 所以第一次total + currentValue为30,那么下一次的total就成了30。
————————————————————————————————————————————————
第二次 total +currentValue时,这里的total是上一次total + currentValue的值:30,所以这次是30 +
currentValue,这时候的cuurentValue为50,所以这次的total + currentValue值为80,也就是下一次total为80。
累加过程就是这样的,解释清楚第一次的total是什么值以及每次total用的是上一次累加值,应该就能看懂这reduce了
如何使用新方法
讲完了三个数组方法,接下来就是把它们投入使用的时候了
为了达成函数式编程,我们要知道它们的返回值
filter:返回新数组
map:返回新数组
reduce:返回一个值
那么我们是不是可以用filter返回的数组直接调用map,然后用map返回的数组直接调用reduce,最后把reduce返回的值交给一个sum即可
可以理解为:filter的返回值我们不去赋值给新数组而是拿来进行map方法,这样我们就可以少创建数组了
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
let sum = 0
sum = arr.filter(function (n) {
return n <= 60
}) //这里就是filter的返回值。紧接着用这返回值进行map方法
.map(function (n) {
return n * 2
}) //这就是map的返回值,紧接着用返回值进行reduce方法
.reduce(function (pervValue, n) {
return pervValue + n
}) //最后将reduce返回值赋值给sum
console.log(sum)
再一步优化
其实上面的链式函数,我们还可以给它进行优化,使用ES6新增的箭头函数
// 这是再简化,通过es6的箭头函数
// 怎么样,是不是感受到了函数式编程和es6的魅力
let arr = [30, 50, 142, 305, 20, 16, 66, 77, 88]
let sum = arr.filter(n => n <= 60).map(n => n * 2).reduce((preValue, n) => preValue + n)
console.log(sum)
结果是一样的,我们从最开始的三个循环创建两个新数组的15行代码,变成了这简单的一行代码,这就是函数式编程和ES6的魅力!
这样看代码不好观看,让我们直接看看在编译器上,这一行代码是多么的漂亮
总结
掌握这三个高级数组方法,妈妈再也不用担心我只会for循环啦!
当然ES6中新增的数组方法还有forEach,some,every,这几个方法非常简单了,这里就不提了