数组的方法和作用 是否操作原数据

5 阅读5分钟

JavaScript 数组方法可按「是否修改原数组」核心分为 修改原数组(变异方法)  和 不修改原数组(非变异方法)  两大类,以下是全量方法的作用、是否改原数组及示例,附清晰分类和总结:

一、修改原数组的方法(变异方法)

这类方法会直接改变原数组的内容 / 结构,返回值多为新长度、被删除元素或修改后的数组(但核心是原数组已变)。

方法名核心作用是否修改原数组示例
push(...items)向数组末尾添加 1 个 / 多个元素,返回新数组长度✅ 是const arr = [1]; arr.push(2); // arr → [1,2],返回 2
pop()删除数组最后一个元素,返回被删除的元素✅ 是const arr = [1,2]; arr.pop(); // arr → [1],返回 2
shift()删除数组第一个元素,返回被删除的元素✅ 是const arr = [1,2]; arr.shift(); // arr → [2],返回 1
unshift(...items)向数组开头添加 1 个 / 多个元素,返回新数组长度✅ 是const arr = [2]; arr.unshift(1); // arr → [1,2],返回 2
splice(start, delCount, ...add)删除 / 插入 / 替换元素(最灵活的修改方法),返回被删除的元素数组✅ 是const arr = [1,2,3]; arr.splice(1,1,4); // arr → [1,4,3],返回 [2]
sort([compareFn])对数组排序(默认按字符串 Unicode 码点),返回排序后的数组✅ 是const arr = [3,1,2]; arr.sort((a,b)=>a-b); // arr → [1,2,3]
reverse()反转数组元素顺序,返回反转后的数组✅ 是const arr = [1,2]; arr.reverse(); // arr → [2,1]
fill(value, start, end)用指定值填充数组指定范围(左闭右开),返回填充后的数组✅ 是const arr = [1,2,3]; arr.fill(0,1,2); // arr → [1,0,3]
copyWithin(target, start, end)复制指定范围元素到目标位置,返回修改后的数组✅ 是const arr = [1,2,3,4]; arr.copyWithin(0,2); // arr → [3,4,3,4]

二、不修改原数组的方法(非变异方法)

这类方法仅返回新值 / 新数组,原数组始终保持不变(核心:只读不写)。

方法名核心作用是否修改原数组示例
concat(...arrays)合并多个数组 / 值,返回新数组❌ 否[1].concat([2]); // 返回 [1,2],原数组 [1] 不变
slice(start, end)截取数组指定范围(左闭右开),返回新数组❌ 否[1,2,3].slice(1,2); // 返回 [2],原数组不变
join([sep])将数组元素拼接为字符串(默认逗号分隔),返回字符串❌ 否[1,2].join('-'); // 返回 "1-2",原数组不变
toString()转为字符串(等价于 join(',')),返回字符串❌ 否[1,2].toString(); // 返回 "1,2"
indexOf(val, from)查找元素首次出现的索引,找不到返回 -1,返回数字❌ 否[1,2,3].indexOf(2); // 返回 1
lastIndexOf(val, from)查找元素最后出现的索引,找不到返回 -1,返回数字❌ 否[1,2,2].lastIndexOf(2); // 返回 2
includes(val, from)判断数组是否包含指定元素,返回布尔值❌ 否[1,2].includes(3); // 返回 false
find(callback)查找第一个满足回调条件的元素,找不到返回 undefined❌ 否[1,2,3].find(item => item>1); // 返回 2
findIndex(callback)查找第一个满足回调条件的元素索引,找不到返回 -1❌ 否[1,2,3].findIndex(item => item>1); // 返回 1
filter(callback)过滤出满足回调条件的元素,返回新数组❌ 否[1,2,3].filter(item => item>1); // 返回 [2,3]
map(callback)遍历数组,每个元素经回调处理后返回新值,组成新数组❌ 否[1,2].map(item => item*2); // 返回 [2,4]
reduce(callback, init)归并 / 累加,将数组转为单个值(从左到右),返回最终值❌ 否[1,2,3].reduce((sum, item)=>sum+item, 0); // 返回 6
reduceRight(callback)归并 / 累加(从右到左),其余同 reduce❌ 否[1,2,3].reduceRight((sum, item)=>sum+item, 0); // 返回 6
flat(depth)扁平化数组(默认深度 1),返回新数组❌ 否[1,[2,[3]]].flat(2); // 返回 [1,2,3]
flatMap(callback)先 map 再 flat(1),返回新数组❌ 否[1,2].flatMap(item=>[item, item*2]); // 返回 [1,2,2,4]
entries()返回数组迭代器(键值对:[索引, 值]❌ 否[1,2].entries(); // 迭代器:{0: [0,1], 1: [1,2]}
keys()返回数组索引迭代器❌ 否[1,2].keys(); // 迭代器:{0:0, 1:1}
values()返回数组值迭代器❌ 否[1,2].values(); // 迭代器:{0:1, 1:2}

三、特殊遍历方法:forEach

  • 作用:遍历数组,为每个元素执行回调函数,无返回值(始终返回 undefined)。

  • 是否修改原数组:方法本身不修改,但回调内可手动修改原数组(如 arr[index] = 新值)。

  • 示例:

    js

    const arr = [1,2];
    // 方法本身不改,但回调手动改原数组
    arr.forEach((item, index) => {
      arr[index] = item * 2; 
    });
    console.log(arr); // [2,4]
    

四、Array 静态方法(类级方法)

挂载在 Array 类上,用于创建数组,不修改任何原对象,返回新数组:

方法名核心作用是否修改原对象
Array.from(iter)将类数组 / 可迭代对象(如 arguments、字符串)转为数组,返回新数组❌ 否
Array.of(...args)创建数组(解决 new Array 的坑:new Array(2) 是长度 2 的空数组,Array.of(2) 是 [2]❌ 否

核心总结

类型核心特征典型方法
修改原数组直接改变原数组结构 / 值push/pop/splice/sort/reverse
不修改原数组返回新值 / 新数组,原数组不变map/filter/slice/concat/reduce
遍历方法仅执行回调,本身不修改原数组forEach(回调可手动改)

注意点

  1. sort 排序陷阱:默认按字符串 Unicode 排序,数值排序需传比较函数:arr.sort((a,b) => a-b)(升序)、arr.sort((a,b) => b-a)(降序)。
  2. splice 灵活性splice(start, 0, val) 是插入元素,splice(start, 1) 是删除元素,splice(start, 1, val) 是替换元素。
  3. 不可变编程:如需避免修改原数组,优先用 map/filter/slice/concat 等,而非 push/splice 等变异方法。