Javascript Array API

227 阅读7分钟

概要

这篇专题旨在记录一些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"]