JavaScript 数组全攻略:从基础到高级用法 🚀

211 阅读4分钟

前言

JavaScript 数组是前端开发中最常用的数据结构之一,它灵活强大但也有一些"坑"。本文将全面介绍数组的特性、常用API及注意事项,助你成为数组操作高手!

认识 JavaScript 数组 📚

JavaScript 数组与其他语言不同:

  • 🔢 长度不固定:可以动态扩容
  • 🎭 类型不固定:一个数组可以包含多种数据类型
  • 🏷️ 具有哈希特性:可以像对象一样使用非数字键
const arr = [1, 'two', {name: 'three'}, [4]];
arr['customKey'] = 'value'; // 可行但不推荐

数组初始化方法 🏗️

1. 数组字面量 (推荐)

const arr1 = [1, 2, 3]; // 最常用的方式

2. new Array 构造函数

const arr2 = new Array(5); // 创建长度为5的空数组

⚠️ 注意new Array(5) 创建的数组是"空槽位"(empty),不是填充了undefined。这会影响遍历:

const arr = new Array(3);
console.log(arr); // [empty × 3]

for (let key in arr) {
  console.log(key); // 不会执行,因为空槽位不可枚举
}

3. 使用 fill 填充数组

const arr3 = new Array(5).fill(undefined); // 真正填充了undefined

4. 静态方法 Array.of

console.log(Array.of(1, 2, 3)); // [1, 2, 3]

5. 静态方法 Array.from (强大!)

// 生成字母表
console.log(Array.from(new Array(26), (val, index) => {
  return String.fromCodePoint(65 + index);
}));
// ["A", "B", "C", ..., "Z"]
特性Array.ofArray.from
主要目的创建包含参数的新数组转换类数组/可迭代对象为真数组
参数处理直接使用参数作为数组元素处理第一个参数并可选映射
参数数量任意数量参数1-3个参数(源, mapFn, thisArg)
特殊行为无,参数总是成为元素可以处理类数组和可迭代对象
典型用例替代 new Array() 的歧义情况转换 DOM 集合、字符串、生成器等
  • 当需要直接创建包含特定元素的数组时,使用 Array.of
  • 当需要转换或映射类数组/可迭代对象时,使用 Array.from
  • Array.from 功能更强大,支持映射转换,而 Array.of 更专注于解决构造函数歧义问题

数组遍历方法 🔍

1. 传统 for 循环

for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

✅ 优点:性能最好
❌ 缺点:可读性较差

2. for...in (不推荐用于数组)

for (let key in arr) {
  console.log(key, arr[key]);
}

⚠️ 注意:会遍历所有可枚举属性,包括非数字键,原型链上面的数据也会枚举

3. for...of (推荐)

for (let item of arr) {
  console.log(item);
}

如果想详细了解for ... infor ... of 之前的区别可以看JavaScript 中的 for...in 和 for...of 循环详解

4. entries() 获取索引和值

for (const [index, value] of arr.entries()) {
  console.log(index, value);
}

5. forEach

arr.forEach((item, index) => {
  console.log(index, item);
});

⚠️ 注意:无法使用break中断循环,return也只能跳过当前项,如果要遍历所有项可以使用someevery进行检测

数组转换与排序

1. sort - 排序

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

// 默认按字符串排序
unsorted.sort(); // [1, 2, 3, 4]

// 自定义排序
unsorted.sort((a, b) => b - a); // [4, 3, 2, 1]

2. reverse - 反转

const arr = [1, 2, 3];
arr.reverse(); // [3, 2, 1]

3. flat/flatMap - 扁平化

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

// 扁平化一层
nested.flat(); // [1, 2, [3, [4]]]

// 扁平化所有层
nested.flat(Infinity); // [1, 2, 3, 4]

// flatMap = map + flat(1)
const phrases = ["hello world", "goodbye moon"];
const words = phrases.flatMap(phrase => phrase.split(' ')); 
// ["hello", "world", "goodbye", "moon"]

实用数组方法 🛠️

1. reduce - 数组归约

// 求和
console.log([1, 2, 3, 4, 5, 6].reduce((prev, curr) => {
  return prev + curr;
}, 0)); // 21

2. map - 数组映射

const doubled = [1, 2, 3].map(x => x * 2); // [2, 4, 6]

3. filter - 数组过滤

const evens = [1, 2, 3, 4].filter(x => x % 2 === 0); // [2, 4]

4. find/findIndex - 查找元素

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

// find - 查找第一个符合条件的元素
const bob = users.find(user => user.name === 'Bob');

// findIndex - 查找第一个符合条件的元素的索引
const bobIndex = users.findIndex(user => user.name === 'Bob');

// includes - 检查是否包含某元素
const hasTwo = numbers.includes(2); // true

// indexOf/lastIndexOf - 查找元素位置
const idx = numbers.indexOf(2); // 1

5. some/every - 条件检测

// some - 是否有元素满足条件
const hasEven = numbers.some(num => num % 2 === 0); // true

// every - 是否所有元素都满足条件
const allEven = numbers.every(num => num % 2 === 0); // false

高级技巧与注意事项 ⚠️

  1. 稀疏数组问题

    const sparse = new Array(5);
    sparse[2] = 'value';
    console.log(sparse); // [empty × 2, "value", empty × 2]
    

    稀疏数组在某些方法中表现可能不符合预期

  2. 原型方法检查

    const arr = new Array(5);
    console.log(arr.hasOwnProperty(0)); // false
    
  3. 性能考虑:对于大型数组,传统for循环通常性能最好

  4. 避免修改数组长度:直接修改length可能导致意外行为

    const arr = [1, 2, 3];
    arr.length = 1; // arr现在是[1]
    

总结 🎯

JavaScript数组功能强大但也有一些"陷阱"。掌握各种初始化方法、遍历方式和实用API,能让你在开发中游刃有余。记住:

  • 🏆 优先使用数组字面量[]创建数组
  • 🔄 遍历推荐for...offorEach
  • 🧠 理解稀疏数组和空槽位的区别
  • ⚡ 根据场景选择合适的数组方法

希望这篇指南能帮助你更好地理解和运用JavaScript数组!

本文很多都是参考Array,里面有很多的关于数组的原型API

image.png