JavaScript Array [](保姆级教程)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 JavaScript 开发中,数组(Array)是处理数据的核心工具之一。它像一个灵活的收纳盒,可以存放多种类型的数据,并支持高效的操作。无论是处理用户输入、管理动态数据,还是构建复杂的应用逻辑,数组都是开发者最常依赖的数据结构。本文将从基础概念到高级技巧,系统性地解析 JavaScript 数组的特性与使用方法,帮助初学者和中级开发者掌握这一重要工具。


一、数组的基本概念与特性

1.1 什么是数组?

JavaScript 数组(Array)是一种 有序的、可变的集合数据结构,用于存储多个值。每个值称为数组的“元素”(Element),并按照**索引(Index)**依次排列。索引从 0 开始,因此第一个元素的索引是 0,第二个是 1,依此类推。

比喻:可以把数组想象成一个抽屉柜,每个抽屉都有编号(索引),存放不同的物品(元素)。例如:

const myArray = ["苹果", "香蕉", "橘子"];
// 索引 0 → "苹果",索引 1 → "香蕉",索引 2 → "橘子"

1.2 数组的特性

  • 动态性:数组长度可变,支持增删元素。
  • 异构性:元素可以是任意类型(数字、字符串、对象、函数等)。
  • 引用类型:数组是对象,赋值操作会传递引用(即“地址”),而非复制数据本身。

引用类型的比喻

const arr1 = [1, 2, 3];
const arr2 = arr1; // arr2 是 arr1 的“影子”,指向同一块内存  
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4] → 修改 arr2 会影响 arr1  

二、创建与访问数组元素

2.1 数组的创建方式

JavaScript 提供了多种创建数组的方式:

方法一:字面量语法(Literal)

这是最常用的方式,语法简洁:

const fruits = ["apple", "banana", "orange"];

方法二:构造函数 Array()

通过 new Array() 初始化数组,但需注意参数传递方式:

// 方式一:传入元素列表  
const numbers = new Array(1, 2, 3); // [1, 2, 3]  

// 方式二:传入长度(需谨慎使用)  
const emptyArray = new Array(3); // [empty ×3],元素为 undefined  

2.2 访问与修改元素

通过索引可以直接读取或修改元素:

const colors = ["red", "green", "blue"];  
console.log(colors[0]); // "red"  

colors[1] = "yellow";  
console.log(colors); // ["red", "yellow", "blue"]  

注意

  • 如果索引超出范围(如 colors[10]),会返回 undefined
  • 负数索引(如 colors[-1])在 JavaScript 中无效。

三、数组的核心操作方法

JavaScript 提供了丰富的内置方法,覆盖增删、遍历、转换等场景。以下列举常用方法,并通过表格对比其功能与用法:

方法功能描述示例代码
push()在末尾添加元素并返回新长度arr.push("newItem") → 修改原数组
pop()移除末尾元素并返回该元素const lastItem = arr.pop()
unshift()在开头添加元素并返回新长度arr.unshift("firstItem") → 修改原数组
shift()移除开头元素并返回该元素const firstItem = arr.shift()
slice(start, end)截取子数组(不修改原数组)const subArr = arr.slice(1, 3)
splice()修改数组(增删元素)arr.splice(2, 0, "new") → 插入元素
map()遍历并生成新数组arr.map(item => item * 2)
filter()筛选符合条件的元素arr.filter(num => num > 5)

3.1 常用方法详解

3.1.1 map():遍历与转换

map() 方法对数组的每个元素执行回调函数,并返回一个新数组(不修改原数组)。

const numbers = [1, 2, 3];  
const doubled = numbers.map(num => num * 2);  
console.log(doubled); // [2, 4, 6]  
console.log(numbers); // [1, 2, 3] → 原数组未变  

3.1.2 filter():条件筛选

filter() 根据回调函数的返回值(true/false)筛选元素:

const evenNumbers = [1, 2, 3, 4].filter(num => num % 2 === 0);  
console.log(evenNumbers); // [2, 4]  

3.1.3 reduce():聚合计算

reduce() 可将数组元素“累积”为单一值,常用于求和、统计等场景:

const sum = [1, 2, 3, 4].reduce((acc, curr) => acc + curr, 0);  
console.log(sum); // 10 → 初始值为 0  

四、数组的高级技巧与注意事项

4.1 判断元素是否存在

可以通过 includes()indexOf() 方法快速判断元素是否存在于数组中:

const letters = ["a", "b", "c"];  
console.log(letters.includes("b")); // true  
console.log(letters.indexOf("d") !== -1); // false  

4.2 合并与拆分数组

  • 合并:使用扩展运算符(...)或 concat() 方法:

    const arr1 = [1, 2];  
    const arr2 = [3, 4];  
    const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]  
    
  • 拆分:通过 slice()splice() 实现,但需注意副作用:

    const arr = [1, 2, 3, 4];  
    const firstTwo = arr.slice(0, 2); // [1, 2] → 无副作用  
    arr.splice(2, 2); // 移除索引 2 开始的 2 个元素 → arr 变为 [1, 2]  
    

4.3 处理空数组与边界情况

  • 空数组的判断:直接比较 array.length === 0,或使用 !array.length
  • 避免索引越界:操作数组前建议先检查长度,例如:
    function getLastElement(arr) {  
      return arr.length > 0 ? arr[arr.length - 1] : null;  
    }  
    

五、数组的内存机制与性能优化

5.1 引用类型的内存占用

数组作为对象,存储的是元素的“引用”而非值本身。因此,修改数组元素会影响所有指向该数组的变量:

let arrA = [1, 2];  
let arrB = arrA;  
arrB[0] = 100;  
console.log(arrA); // [100, 2] → arrA 和 arrB 指向同一内存  

5.2 性能优化建议

  • 避免频繁修改大型数组splice() 等操作在长数组中可能耗时较长。
  • 使用原生方法代替循环:如 map()filter() 内部优化更好。
  • 冻结数组:若数组无需修改,可使用 Object.freeze() 防止意外更改:
    const immutableArr = Object.freeze([1, 2, 3]);  
    immutableArr.push(4); // 抛出错误(非严格模式下可能静默失败)  
    

六、实际案例:构建一个待办事项列表

6.1 需求分析

假设需要实现一个简单的待办事项列表,要求支持以下功能:

  1. 添加新任务;
  2. 标记任务为已完成;
  3. 删除任务;
  4. 展示任务列表。

6.2 代码实现

class TodoList {  
  constructor() {  
    this.todos = [];  
  }  

  addTodo(task) {  
    this.todos.push({ text: task, completed: false });  
  }  

  toggleCompleted(index) {  
    if (index >= 0 && index < this.todos.length) {  
      this.todos[index].completed = !this.todos[index].completed;  
    }  
  }  

  removeTodo(index) {  
    this.todos.splice(index, 1);  
  }  

  displayTodos() {  
    console.log("待办事项:");  
    this.todos.forEach((todo, idx) => {  
      console.log(`${idx}: [${todo.completed ? "✓" : " "}] ${todo.text}`);  
    });  
  }  
}  

// 使用示例  
const list = new TodoList();  
list.addTodo("学习 JavaScript 数组");  
list.addTodo("完成项目代码");  
list.displayTodos();  
list.toggleCompleted(0);  
list.removeTodo(1);  
list.displayTodos();  

6.3 输出结果

待办事项:
0: [ ] 学习 JavaScript 数组
1: [ ] 完成项目代码  
待办事项:  
0: [✓] 学习 JavaScript 数组  

结论

JavaScript 数组是一个功能强大且灵活的数据结构,掌握其核心方法与特性,能够显著提升开发效率。从基础的增删操作到高级的内存管理,数组的应用场景贯穿前端开发的各个环节。对于初学者,建议通过实际项目(如待办事项列表)巩固知识;中级开发者则可深入研究数组的原型链方法、迭代器等底层机制,进一步优化代码性能。

记住,实践是掌握数组的最佳途径。通过不断编写代码、调试问题,你将逐渐熟悉 JavaScript Array 的“魔法”,并能用它解决更复杂的开发挑战!

最新发布