概要
这篇专题旨在记录一些Javascript 数组操作操作方法的细节之处,并给出一些场景去利用这些细节
map方法
先通过一个示例简单了解下map方法:
const array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
概念:map方法返回一个新数组,新数组中的每个元素是原数组中每个元素调用一次提供给map方法函数后的返回值。
参数:有两个一级参数,回调函数和指定的this
callback:生成新数组元素的函数,使用三个参数,实际工作中,之前一直以为只有currentValue这一个参数。currentValue:callback数组中正在处理的当前元素index(可选):callback数组中正在处理的当前元素的索引array(可选):原数组本身
thisArg(可选):执行callback函数时该值被用作callback函数中的this,这要求callback函数不能使用箭头函数
Note:map方法不修改原数组本身
Note:map、reduce、filter支持链式调用,这是一个非常实用的功能
使用map方法格式化对象数组
以下代码通过一定的方式格式化原对象数组,并返回一个新的数组,但不影响原有数组本身
const kvArray = [
{ key: 1, value: 10 },
{ key: 2, value: 20 },
{ key: 3, value: 30 },
]
const formatKvArray = kvArray.map(({ key, value }) => {
return { [key]: value };
})
console.log(formatKvArray); // [{1:10},{2:20},{3:30}]
在Javascript库中用于渲染列表
像react这样的Javascript库利用map()方法来渲染列表中的项目,下面展示一个react的无状态组件:
import React from 'react'
import ReactDOM from 'react-dom'
const names = ['foo', 'bar', 'mike', 'jean'];
const NameList = () => (
<div>
<ul>{names.map(name => <li key={name}>{name}</li>)}</ul>
</div>
)
ReactDOM.render(<NameList />, document.getElementById('root'));
在JSX语法中,经常要求根据数组中元素生成符合xml规范的元素标签,那么map方法再合适不过
reduce方法
简介:reduce方法对数组中的每个元素执行一个由您提供的reduce函数(升序执行),将其结果汇总为单个返回值。
reduce方法的参数
callback:数组中的每个值都会调用一次该callback函数,该回调包含四个参数:accumulator:累计器累计回调的返回值,它是上一次调用回调时返回的累积值currentValue:数组中正在处理的元素index(可选):数组中正在处理的当前元素索引,如果提供了initialValue,则起始索引为0,否则索引从1开始array(可选):调用reduce的源数组
initialValue(可选):作为第一次调用callback函数时的第一个参数的值,如果没有提供初始值,则将使用数组中的第一个元素,在没有初始值的空数组上调用reduce会报错。
// 使用reduce对数组中元素求和
const arr = [1,2,3,4];
const callback = (acc, cur) => acc + cur;
console.log(arr.reduce(callback)); // 10
// 这里的 5 便是传入的 initialValue
console.log(arr.reduce(callback, 5)); // 15
-
描述:reduce方法为数组中每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,接收四个参数:accumulate:累计器currentValue:当前值currentIndex:当前索引array数组:数组回调函数第一次执行时,accumulate 和 currentValue 的取值有两种情况,如果调用 reduce 方法时提供了 initialValue ,accumulate 取值为 initialValue ,currentValue 取数组中第一个值。如果没有提供 initialValue ,那么 accumulate 取数组中的第一个值,currentValue 取数组中的第二个值。
-
Note: 如果没有提供 initialValue ,reduce 方法回调函数的起始索引为1,否则为0
reduce方法的使用场景
将二维数组转为一维数组:
const arr = [[0, 1], [2, 3], [4, 5]];
const result = arr.reduce((acc, cur) => [...acc, ...cur])
console.log(result); // [0, 1, 2, 3, 4, 5]
求和:
// ① 对元素全是Number类型的数组求和
const arr = [1,2,3,4,5];
console.log(arr.reduce((acc, cur) => acc + cur));
// 15
// ② 累加对象数组中的值,这里需要明确:要累加对象数组中包含的值,必须提供初始值
const initialValue = 0;
const sum = [{x:1}, {x:2}, {x:3}].reduce((acc, cur) => acc + cur.x, initialValue)
console.log(sum); // 6
计算数组中每个元素出现的次数:
const names = ['teacher', 'student', 'teacher', 'student', 'student','developer'];
const countedNames = names.reduce((acc, cur) => {
if (cur in acc) {
acc[cur]++;
} else {
acc[cur] = 1;
}
return acc;
}, {});
console.log(countedNames);
// {teacher: 2, student: 3, developer: 1}
按属性对object进行分类:
const people = [
{ name: 'Alice', age: 21 },
{ name: 'Max', age: 20 },
{ name: 'Jane', age: 20 },
];
function groupBy(arr, pro){
return arr.reduce((acc, cur) => {
const key = cur[pro];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(cur);
return acc;
}, {});
}
const groupedPeople = groupBy(people, 'age');
console.log(groupedPeople);
// {
// 20: [
// { name: 'Max', age: 20 },
// { name: 'Jane', age: 20 }
// ],
// 21: [{ name: 'Alice', age: 21 }]
// }
实现 lodash 中的 FlowRight 函数:
lodash 中的 FlowRight 函数是函数式编程中的组合函数概念,利用流式操作对数据依次处理并返回,reduce 方法可以很好的实现组合函数
Note:FlowRight 函数只接受纯函数作为参数,并且这些函数只接受一个数据参数,通常情况下,这些函数都是柯里化后的函数,并且只接受一个数据作为参数
const flowRight = (...args) => initialValue => args.reverse().reduce((acc, cur) => cur(acc), initialValue)
function reverse(arr) {
return arr.reverse()
}
function first (arr) {
return arr[0]
}
// 将取出数组最后一个元素的操作组合成一个函数
const compose = flowRight(first,reverse)
console.log(compose([1,2,3,4]))
// 4
some方法
-
简介:some 方法对数组中的每一项调用一次你传入的函数,如果其中一次调用的结果为 true,则 some 函数停止执行并返回 true -
检查数组中元素是否存在偶数:
const arr = [1,2,3,4,5]
function hasEven(arr) {
return arr.some(item => item % 2 === 0)
}
console.log(hasEven(arr))
// true
检查数组中元素是否包含字符串类型:
const arr = [1,2,3,4,5]
function isStringOfArr(arr) {
return arr.some(item => Object.prototype.toString.call(item) === '[object String]')
}
console.log(isStringOfArr(arr))
// false
every方法
-
简介:every 方法对数组中的每一项调用一次你传入的函数,与 some 不同的是,只有每一次调用的结果都是 true 时,才会返回true,而且 every 方法一定会将数组中的每一项都调用一次 -
检查数组中元素是否包含字符串类型:
const arr = ['1','2','3','4','5']
function isStringOfArr(arr) {
return arr.every(item => Object.prototype.toString.call(item) === '[object String]')
}
console.log(isStringOfArr(arr))
// true
findIndex方法
-
简介:findIndex方法可以用来寻找数组中第一个符合条件的元素的索引,如果没有找到则返回-1,与该方法极其类似的方法是 find 方法,find 方法返回符合条件的第一个值而不是其索引 -
找到数组中是否存在4,有的话返回其索引:
const arr = [1,2,3,4,5]
console.log(arr.findIndex((item) => item === 4))
// 3
find方法
-
简介:find 方法会依次遍历数组,并将数组中每一项调用一次你提供的函数,如果发现符合条件的元素,立即返回该元素并终止遍历 -
找到数组中第一个大于10的元素:
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found);
// expected output: 12
includes方法
简介:includes 方法用来判断数组是否包含一个指定的值,如果包含则返回 true,否则返回 false
const array1 = [1, 2, 3];
console.log(array1.includes(2));
// expected output: true
const pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));
// expected output: true
console.log(pets.includes('at'));
// expected output: false
slice方法
-
简介:slice 方法返回一个新的数组,新数组的成员由方法调用时传入时的下标决定 -
返回数组的第3个元素至5个元素:
const animals = ['1', '2', '3', '4', '5', '6', '7'];
console.log(animals.slice(3,6))
// [ '4', '5', '6' ]
返回数组的最后一个元素:
const animals = ['1', '2', '3', '4', '5', '6', '7'];
console.log(animals.slice(-1))
// [ '7' ]
返回数组的最后三个元素:
const animals = ['1', '2', '3', '4', '5', '6', '7'];
console.log(animals.slice(-3))
// [ '5', '6', '7' ]
splice方法
简介:splice 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容,此方法会修改原数组
const months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at index 1
console.log(months);
// expected output: Array ["Jan", "Feb", "March", "April", "June"]
months.splice(4, 1, 'May');
// replaces 1 element at index 4
console.log(months);
// expected output: Array ["Jan", "Feb", "March", "April", "May"]