数组的API

11 阅读4分钟

一、数组创建与转换

方法作用示例
Array.from()将类数组对象(如arguments、DOM节点列表)或可迭代对象转为数组。Array.from('hello') // ['h', 'e', 'l', 'l', 'o']
Array.of()创建包含任意数量参数的数组(解决Array()的特殊情况)。Array.of(3) // [3](区别于Array(3)创建长度为3的空数组)
Array.isArray()判断是否为数组(优于instanceof,跨iframe场景可靠)。Array.isArray([]) // true

二、元素增删改查(改变原数组)

方法作用示例
push()尾部添加一个或多个元素,返回新长度。[1, 2].push(3) // 返回3,数组变为[1, 2, 3]
pop()尾部删除一个元素,返回被删除的元素。[1, 2, 3].pop() // 返回3,数组变为[1, 2]
unshift()头部添加一个或多个元素,返回新长度。[2, 3].unshift(1) // 返回3,数组变为[1, 2, 3]
shift()头部删除一个元素,返回被删除的元素。[1, 2, 3].shift() // 返回1,数组变为[2, 3]
splice()删除/替换/插入元素,返回被删除的元素。[1, 2, 3].splice(1, 1, 'a') // 返回[2],数组变为[1, 'a', 3]
reverse()反转数组元素顺序。[1, 2, 3].reverse() // [3, 2, 1]
sort()排序数组(默认按字符串Unicode码点)。[3, 1, 2].sort() // [1, 2, 3](字符串排序需注意:[10, 2].sort()结果为[10, 2]

三、遍历与转换(不改变原数组)

方法作用示例
map()遍历数组,返回由每个元素处理后的新数组。[1, 2].map(x => x * 2) // [2, 4]
filter()过滤数组,返回满足条件的元素组成的新数组。[1, 2, 3].filter(x => x > 2) // [3]
reduce()累计计算,从左到右将数组元素累积为单个值。[1, 2, 3].reduce((sum, x) => sum + x, 0) // 6(初始值为0)
flat()扁平化数组,将多维数组降为一维(默认深度1)。[1, [2, 3]].flat() // [1, 2, 3]
flatMap()mapflat,比单独调用更高效。['a b', 'c d'].flatMap(x => x.split(' ')) // ['a', 'b', 'c', 'd']
slice()截取数组,返回指定位置的新数组(不包含结束位置)。[1, 2, 3].slice(1, 3) // [2, 3]
join()连接数组元素为字符串,指定分隔符(默认逗号)。[1, 2, 3].join('-') // "1-2-3"
concat()合并数组,返回新数组。[1].concat([2, 3]) // [1, 2, 3]

四、查找与判断

方法作用示例
find()查找元素,返回第一个满足条件的元素(否则undefined)。[1, 2, 3].find(x => x > 1) // 2
findIndex()查找索引,返回第一个满足条件的元素索引(否则-1)。[1, 2, 3].findIndex(x => x > 1) // 1
includes()判断存在,返回是否包含某个值(支持NaN,区别于indexOf)。[1, 2, NaN].includes(NaN) // true
some()条件判断,任一元素满足条件则返回true[1, 2, 3].some(x => x > 2) // true
every()条件判断,所有元素满足条件则返回true[1, 2, 3].every(x => x > 0) // true

五、迭代器与异步操作

方法作用示例
forEach()遍历数组,对每个元素执行回调(无返回值)。[1, 2].forEach(x => console.log(x))
entries()返回迭代器,包含[index, value]对。[...['a', 'b'].entries()] // [[0, 'a'], [1, 'b']]
keys()返回索引迭代器[...['a', 'b'].keys()] // [0, 1]
values()返回值迭代器(ES2016+,浏览器支持有限)。[...['a', 'b'].values()] // ['a', 'b']
at()按索引访问(支持负索引,表示从末尾开始)。[1, 2, 3].at(-1) // 3

六、问题

1. 问:map()forEach()的区别?

    • map()返回新数组,forEach()无返回值(常用于副作用操作,如日志打印);
    • map()可链式调用(如arr.map().filter()),forEach()不能。

2. 问:reduce()的典型应用场景?

    • 求和/乘积[1, 2, 3].reduce((a, b) => a + b, 0)
    • 数组转对象[{id:1, name:'a'}].reduce((obj, item) => ({...obj, [item.id]: item}), {})
    • 扁平化数组[[1, 2], [3]].reduce((acc, cur) => acc.concat(cur), [])

3. 问:如何高效删除数组中的重复元素?

  • // 方法1:Set(ES6+,简单高效)
    const unique = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]
    
    // 方法2:filter+indexOf(兼容性好)
    const unique = [1, 2, 2, 3].filter((item, index, arr) => arr.indexOf(item) === index);
    

4. 问:flat()flatMap()的性能对比?


  • flatMap()通常更高效,因为它在一次遍历中完成mapflat操作,避免创建中间数组。例如:
    // 处理大数据时性能优势明显
    const arr = Array(1000).fill([1, 2]);
    arr.flatMap(x => x * 2); // 比先map再flat更高效
    

七、总结

“JavaScript数组API可按功能分为五类:

  1. 创建与转换fromofisArray
  2. 增删改查push/popunshift/shiftsplicesort
  3. 遍历转换mapfilterreduceflat
  4. 查找判断findincludessome/every
  5. 迭代器entrieskeysvalues

面试时需注意方法是否改变原数组(如splice vs slice),以及场景优化(如flatMap替代map+flat)。”