JavaScript数组:从基础到高级,掌握这些技巧让你代码更优雅!

78 阅读3分钟

数组作为JavaScript中最常用的数据结构之一,隐藏着许多令人惊叹的设计哲学和高效技巧。本文将带你深入探索数组的奥秘,让你的代码从平凡走向卓越!

数组声明:两种方式,两种哲学

1. 数组字面量:简洁优雅

// 最常用的声明方式
const arr1 = [1, 2, 3]; 
const arr2 = []; // 空数组

2. Array构造函数:灵活强大

// 创建长度为5的空数组
const arr3 = new Array(5); 
// [empty × 5] - 空槽数组

// 创建包含元素的数组
const arr4 = new Array(1, 2, 3); // [1, 2, 3]

关键区别

  • C++等静态语言:数组长度和类型固定
  • JavaScript:动态类型、自动扩容、支持稀疏数组
  • V8引擎魔法:内部根据元素类型优化存储(数字用连续内存,混合类型用哈希)

数组的隐藏特性:不只是线性结构

JavaScript数组具有类哈希特性

const arr = [1, 2, 3];
arr['customKey'] = 'value'; // 添加非数字属性

// 使用for...in遍历
for (let key in arr) {
  console.log(key); // 输出: "0", "1", "2", "customKey"
}

注意:这种用法虽然可行,但通常不推荐。数组最适合存储有序数据!

数组高级初始化技巧

1. fill() - 统一填充

// 创建5个undefined元素的数组
const arr = new Array(5).fill(undefined); 

// 创建5个0的数组
const zeros = new Array(5).fill(0);

2. Array.of() - 避免构造函数陷阱

// 传统方式的问题
new Array(5); // 创建长度为5的空数组 [empty × 5]
new Array(5, 1); // 创建数组 [5, 1] - 行为不一致!

// Array.of() 统一行为
Array.of(5); // [5]
Array.of(5, 1); // [5, 1]

3. Array.from() - 类数组转换神器

// 字符串转数组
Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']

// 生成字母表
Array.from({ length: 26 }, (_, i) => 
  String.fromCharCode(65 + i)
); // ['A', 'B', ... 'Z']

// 转换NodeList
const divs = Array.from(document.querySelectorAll('div'));

数组遍历:七种武器

1. 技术型循环 - 性能王者

// for循环 - 全能选手
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

// while循环 - 灵活控制
let i = 0;
while (i < arr.length) {
  console.log(arr[i]);
  i++;
}

2. forEach - 简洁优雅

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

局限:无法使用break中断循环

3. 高阶函数 - 声明式编程典范

// map: 数据转换
const doubled = arr.map(num => num * 2);

// filter: 数据筛选
const evens = arr.filter(num => num % 2 === 0);

// find: 元素查找
const firstEven = arr.find(num => num % 2 === 0);

// some/every: 条件检查
const hasNegative = arr.some(num => num < 0);
const allPositive = arr.every(num => num > 0);

4. for...of - 现代循环利器

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

// 获取索引的优雅方式
for (const [index, value] of arr.entries()) {
  console.log(index, value);
}

Reduce:数组的终极武器

基础用法:数组归约

const sum = [1, 2, 3, 4].reduce((acc, curr) => {
  return acc + curr;
}, 0); // 10

高级用法:多功能工具

// 数组转对象
const obj = arr.reduce((acc, item) => {
  acc[item.id] = item;
  return acc;
}, {});

// 数据分组
const grouped = items.reduce((groups, item) => {
  const key = item.category;
  groups[key] = groups[key] || [];
  groups[key].push(item);
  return groups;
}, {});

与React的useReducer:异曲同工

// React中的reducer
function reducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return state + action.value;
    default:
      return state;
  }
}

// 数组reduce
const result = actions.reduce(reducer, initialState);

共同哲学:通过纯函数处理数据流,输入确定则输出确定

性能与最佳实践

  1. 遍历选择

    • 大数据量:优先使用for循环
    • 代码可读性:优先使用map/filter/reduce
    • DOM操作:forEachfor...of
  2. 避免陷阱

    // 稀疏数组问题
    const sparse = new Array(5);
    sparse[10] = 1;
    
    // 使用fill修复
    const dense = new Array(5).fill(undefined);
    
  3. 现代技巧

    // 数组去重
    const unique = [...new Set(arr)];
    
    // 数组切片
    const [first, ...rest] = arr;
    
    // 数组合并
    const merged = [...arr1, ...arr2];
    

结语:数组的艺术

JavaScript数组不仅仅是数据容器,它们是:

  1. 灵活的数据结构 - 可模拟栈、队列、链表
  2. 函数式编程的基石 - 通过map/filter/reduce实现声明式代码
  3. 性能与表达的平衡 - 在不同场景选择最佳遍历方式

掌握数组的奥秘,你的代码将实现从"能用"到"优雅"的蜕变。数组虽小,却蕴含着JavaScript最精妙的设计哲学!