js 数组方法及常见的问题

JavaScript数组的常用方法,然后列出常见的问题。

注意:数组方法可以分为以下几类:变更方法(修改原数组)、访问方法(不修改原数组)、迭代方法等。

一、数组常用方法

  1. 变更方法(修改原数组):
  • push():末尾添加一个或多个元素,返回新长度

  • pop():删除最后一个元素,返回该元素

  • shift():删除第一个元素,返回该元素

  • unshift():开头添加一个或多个元素,返回新长度

  • splice():删除、插入或替换元素,返回被删除的元素组成的数组

  • sort():排序,默认按字符串Unicode码点排序

  • reverse():反转数组

  1. 访问方法(不修改原数组):
  • concat():合并数组,返回新数组

  • slice(start, end):截取数组,返回新数组

  • join(separator):将数组连接成字符串

  • indexOf():返回指定元素第一次出现的索引

  • lastIndexOf():返回指定元素最后一次出现的索引

  • includes():判断是否包含某元素

  1. 迭代方法(不修改原数组,但回调函数可以修改):
  • forEach():遍历数组,无返回值

  • map():对每个元素调用回调,返回新数组

  • filter():过滤,返回满足条件的元素组成的新数组

  • reduce():从左到右累加

  • reduceRight():从右到左累加

  • some():判断是否至少有一个元素满足条件

  • every():判断是否所有元素都满足条件

  • find():返回第一个满足条件的元素

  • findIndex():返回第一个满足条件的元素的索引

  1. ES6+ 新增方法:
  • Array.from():将类数组对象或可迭代对象转换为数组

  • Array.of():将一组值转换为数组

  • fill():填充数组

  • copyWithin():在数组内部复制元素

  • flat():数组扁平化

  • flatMap():先map再flat(1)

二、常见题

  1. 数组去重

  2. 数组扁平化(多维数组转一维)

  3. 数组排序(包括自定义排序)

  4. 数组方法的实现(如实现map、filter、reduce等)

  5. 数组的深拷贝

  6. 数组和类数组的区别及转换

  7. 数组的遍历方法比较(for、forEach、for...in、for...of)

  8. 使用reduce实现复杂功能(如实现map、filter等)

  9. 数组的常见操作(合并、截取、反转等)

  10. 数组的迭代方法的应用(如some、every、find等)

三、常被问的题(示例)

  1. 数组去重的多种实现方式
  • 使用Set

  • 使用filter+indexOf

  • 使用reduce

  • 使用对象键值对

  1. 数组扁平化(多维数组转一维)
  • 递归

  • 使用flat方法

  • 使用reduce递归

  • 使用扩展运算符

  1. 手写数组方法(如map、filter、reduce等)

  2. 数组排序(如按对象的某个属性排序)

  3. 数组的深拷贝(考虑多层嵌套)

  4. 类数组转数组(arguments、NodeList等)

  5. 使用数组方法解决复杂问题(如求交集、并集、差集)

  6. 数组遍历的性能比较

  7. 数组的哪些方法会改变原数组,哪些不会

  8. 数组的空位处理(如[1,,3])

下面我们详细展开一些常见题的解答:

JavaScript 数组方法大全及高频题解析

一、数组核心方法分类

类型 方法 特点
增删改 push()/pop()/shift()/unshift()/splice() 修改原数组
转换 join()/toString()/Array.from()/Array.of() 生成新格式
截取 slice()/concat() 返回新数组
查找 indexOf()/lastIndexOf()/find()/findIndex()/includes() 返回位置或元素
遍历 forEach()/map()/filter()/reduce()/some()/every() 迭代处理
排序 sort()/reverse() 修改原数组
ES6+ flat()/flatMap()/fill()/copyWithin() 新增功能

二、高频题及解析

1. map() vs forEach() 区别?

const arr = [1, 2, 3];

// map:返回新数组
const mapped = arr.map(x => x * 2); // [2, 4, 6]

// forEach:无返回值
arr.forEach(x => console.log(x)); // 1, 2, 3
  • map():返回新数组,适合数据转换
  • forEach():仅遍历,无返回值

2. 实现数组去重(3种方法)

// 方法1:Set(ES6最简单)
const unique1 = [...new Set([1,2,2,3])]; // [1,2,3]

// 方法2:filter + indexOf
const unique2 = [1,2,2,3].filter(
  (item, idx, arr) => arr.indexOf(item) === idx
);

// 方法3:reduce
const unique3 = [1,2,2,3].reduce(
  (acc, cur) => acc.includes(cur) ? acc : [...acc, cur], []
);

3. reduce() 高级用法

// 1. 数组求和
[1,2,3].reduce((sum, n) => sum + n, 0); // 6

// 2. 二维数组转对象
const arr = [['name','Alice'], ['age',30]];
arr.reduce((obj, [key, val]) => ({...obj, [key]: val}), {});

// 3. 实现数组扁平化
const flatten = arr => arr.reduce(
  (flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next), []
);

4. 数组排序陷阱

// 数字排序错误做法
[10, 5, 100].sort(); // [10, 100, 5](按字符串Unicode排序)

// 正确做法
[10, 5, 100].sort((a, b) => a - b); // [5, 10, 100]

// 对象数组排序
const users = [
  {name: 'Alice', age: 30},
  {name: 'Bob', age: 25}
];
users.sort((a, b) => a.age - b.age); // 按年龄升序

5. 数组方法实现原理(手写)

// 手写 map()
Array.prototype.myMap = function(callback) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    result.push(callback(this[i], i, this));
  }
  return result;
};

// 手写 filter()
Array.prototype.myFilter = function(callback) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    if (callback(this[i], i, this)) {
      result.push(this[i]);
    }
  }
  return result;
};

6. 数组空位处理

const arr = [1, , 3]; // 空位

// ES5 方法跳过空位
arr.forEach(x => console.log(x)); // 1, 3

// ES6 方法视空位为 undefined
Array.from(arr); // [1, undefined, 3]
[...arr];        // [1, undefined, 3]

7. 数组扁平化(多维转一维)

const arr = [1, [2, [3, [4]]]];

// 方法1:flat(Infinity)
arr.flat(Infinity); // [1,2,3,4]

// 方法2:reduce + 递归
function flatten(arr) {
  return arr.reduce(
    (acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val), []
  );
}

// 方法3:toString(仅数字数组)
arr.toString().split(',').map(Number);

8. 类数组转真数组

// DOM元素列表
const nodeList = document.querySelectorAll('div');

// 转换方法
const arr1 = Array.from(nodeList);
const arr2 = [...nodeList];
const arr3 = [].slice.call(nodeList);

9. 数组性能对比题

// 创建10万元素数组
const largeArray = Array(100000).fill(0);

// 测试 for vs forEach vs for...of
console.time('for');
for (let i = 0; i < largeArray.length; i++) {} // 最快
console.timeEnd('for');

console.time('forEach');
largeArray.forEach(() => {}); // 次之
console.timeEnd('forEach');

console.time('for...of');
for (const item of largeArray) {} // 最慢
console.timeEnd('for...of');

10. 数组方法链式调用

const data = [
  {id: 1, value: 10, active: true},
  {id: 2, value: 20, active: false},
  {id: 3, value: 30, active: true}
];

// 链式处理:激活状态对象 → 值翻倍 → 求和
const result = data
  .filter(item => item.active)
  .map(item => item.value * 2)
  .reduce((sum, val) => sum + val, 0); // 80

三、数组核心考点总结

  1. 方法特性

    • 哪些方法修改原数组(sort, splice等)
    • 哪些返回新数组(map, filter等)
  2. 性能优化

    • 大数据集避免链式调用(中间数组浪费内存)
    • 遍历优先用 for 循环
  3. ES6+ 特性

    • Array.from() 处理类数组
    • flat() 多维数组扁平化
    • 空位处理差异
  4. 函数式编程

    • map/filter/reduce 组合应用
    • 避免副作用(纯函数)
  5. 手写实现

    • 常考 mapfilterreduce 实现
    • 理解迭代器协议

建议:遇到数组问题先明确需求 - 需要返回新数组还是修改原数组?数据规模如何?是否需要考虑兼容性?掌握核心方法的特性组合使用能解决90%的数组相关问题。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 数组方法备忘单: 添加/删除元素:push(...items) —— 向尾端添加元素,pop() —— 从尾端提取...
    个人观察日记阅读 3,077评论 0 0
  • 由于最近都在freecodecamp上刷代码,运用了很多JavaScript数组的方法,因此做了一份关于JavaS...
    2bc5f46e925b阅读 6,258评论 0 16
  • JavaScript中创建数组有两种方式 (一)使用 Array 构造函数: (二)使用数组字面量表示法: 数组的...
    乙哥驿站阅读 3,142评论 0 1
  • 数组是 js 中最常用到的数据集合,其内置的方法有很多,熟练掌握这些方法,可以有效的提高我们的工作效率,同时对我们...
    魂斗罗小黑阅读 2,615评论 0 1
  • ES3数组方法 join() Array.join()方法将数组中所有元素都转化为字符串并连接在一起,返回最后生成...
    markdown阅读 4,136评论 1 8

友情链接更多精彩内容