数组是JavaScript中最重要的数据结构之一,它为我们提供了一种有序存储和操作数据集合的强大方式。与其他编程语言中的数组概念类似,JavaScript数组允许我们将多个值组织在一起,并通过数字索引来访问这些值。 然而,JavaScript数组的灵活性远超传统意义上的数组,它们实际上是特殊的对象,具有许多独特的特性和强大的内置方法。

理解数组对于JavaScript编程至关重要,因为无论是处理用户界面中的元素列表,还是管理从服务器获取的数据,数组都是不可或缺的工具。 JavaScript数组不仅支持基本的存储和访问操作,还提供了丰富的方法来进行搜索、排序、过滤、转换等高级操作,这些功能让数据处理变得既简单又高效。
创建数组是使用数组的第一步。在JavaScript中,数组可以通过多种方式进行创建,主要包括数组字面量、Array构造函数、Array.of、Array.from等方法。最常见和最推荐的方式是使用数组字面量(即用方括号[]包裹元素),因为它语法简洁、易读且高效,非常适合绝大多数开发场景。
数组字面量使用方括号来包围数组元素,元素之间用逗号分隔。
|// 创建不同类型的数组 let fruits = ['苹果', '香蕉', '橘子']; let numbers = [1, 3, 5, 7]; let mixedData = [42, '文本', true]; console.log("水果:", fruits); console.log("数字:", numbers); console.log("混合数据:", mixedData);
|水果: [ '苹果', '香蕉', '橘子' ] 数字: [ 1, 3, 5, 7 ] 混合数据: [ 42, '文本', true ]
除了数组字面量,我们还可以使用 Array 构造函数来创建数组。Array 构造函数的用法有两种主要形式:
传入一个数字参数:
如果只传入一个数字参数(如 new Array(5)),则会创建一个具有指定长度但内容为空(即稀疏数组,所有索引位置都是空槽)的数组。这在需要预先分配一定长度、后续再填充数据的场景下非常有用。例如,批量生成占位数组、后续通过循环赋值等。
传入多个参数或非数字参数:
如果传入多个参数(如 new Array(1, 2, 3)),或者传入的参数不是单一数字(如 new Array('a')),则会将这些参数作为数组的元素依次填入数组中。这种方式等价于使用数组字面量,但语法上不如字面量直观。
|// 创建一个指定长度的空数组 let emptySlots = new Array(3); console.log("指定长度的数组:", emptySlots); console.log("长度:", emptySlots.length); // 创建包含指定元素的数组 let colors = new Array('红', '绿', '蓝'); console.log("包含元素的数组:", colors);
|指定长度的数组: [ <3 empty items> ] 长度: 3 包含元素的数组: [ '红', '绿', '蓝' ]
在 JavaScript 中,数组是一组有序的数据集合。每个数组元素都通过一个数字索引进行标识,这个索引从 0 开始递增。
例如,第一个元素的索引是 0,第二个元素的索引是 1,以此类推。我们可以使用"方括号语法"来访问和修改数组中的元素:写作 数组名[索引]。
如果要读取某个位置的值,只需写 array[索引],要修改某个元素的值,也可以直接通过赋值语句 array[索引] = 新值 来完成。
例如,arr[2] = 100 会把数组中索引为 2 的元素修改为 100。需要注意的是,如果访问的索引超出了数组的实际长度,返回的结果是 undefined。
此外,使用方括号语法还可以通过变量动态指定索引,非常灵活。这种基于索引的访问和修改方式,是数组操作最基础、最常用的方法。
|let cityList = ['北京', '上海', '广州']; // 访问元素 console.log("第一个城市:", cityList[0]); // 修改元素 cityList[1] = '深圳'; console.log("修改后的数组:", cityList); // 添加新元素 cityList[3] = '杭州'; console.log
|第一个城市: 北京 修改后的数组: [ '北京', '深圳', '广州', '杭州' ] 添加后的数组: [ '北京', '深圳', '广州', '杭州' ]
在 JavaScript 中,数组的每个元素其实是以属性的形式存储在对象中的,其属性名是字符串类型的索引。例如,arr[1] 实际上等价于 arr['1'],因为数字索引会被自动转换为字符串。
这意味着数组本质上是一种特殊的对象,除了可以用数字索引访问元素外,还可以像对象一样为数组添加任意的自定义属性(如 arr['foo'] = 123)。
不过,只有那些可以被解析为非负整数的属性名(如 '0', '1', '2' 等)才会被计入数组的 length 属性,其他字符串属性不会影响数组的长度。
因此,理解数组索引与对象属性之间的这种自动转换和区别,对于正确操作和遍历数组非常重要。
|let testArray = ['A', 'B']; testArray['description'] = '这是一个测试'; console.log("通过数字索引访问:", testArray[0]); console.log("通过字符串索引访问:", testArray['1']); console.log("自定义属性:", testArray.description); console.log("数组长度:", testArray.length);
|通过数字索引访问: A 通过字符串索引访问: B 自定义属性: 这是一个测试 数组长度: 2
数组的 length 属性是数组最核心和独特的特性之一。它不仅仅表示数组当前实际包含的元素数量(即最大索引+1),而且可以被程序员手动修改,从而动态地扩展或截断数组。 例如,当你通过索引为数组添加新元素时,length 会自动增长以反映新的最大索引;反之,如果直接减少 length 的值,数组中对应索引及其之后的元素会被自动删除。 需要注意的是,length 只统计那些以非负整数为索引的元素,其他通过字符串或负数索引添加的属性不会影响 length 的值。 理解 length 的这些行为,对于正确地操作、遍历和管理数组非常关键,尤其是在需要动态调整数组大小或清空数组时。
|let items = ['物品1', '物品2', '物品3']; console.log("原始长度:", items.length); // 截断数组 items.length = 2; console.log("截断后的数组:", items); console.log("截断后的长度:", items.length); // 扩展数组 (创建空槽) items.length = 4
|原始长度: 3 截断后的数组: [ '物品1', '物品2' ] 截断后的长度: 2 扩展后的数组: [ '物品1', '物品2', <2 empty items> ] 扩展后的长度: 4 访问空槽: undefined
JavaScript 提供了多种方法来添加和删除数组元素,常见的有 push、pop、unshift、shift、splice 等。 每种方法的操作位置、返回值和对原数组的影响都不相同。例如,push 和 pop 分别在数组末尾添加和删除元素,而 unshift 和 shift 则在数组开头进行操作。 splice 方法则可以在任意位置插入、删除或替换元素。合理选择这些方法,可以根据实际需求灵活地管理数组内容, 使代码更加清晰、简洁和高效。了解每种方法的具体行为和适用场景,有助于避免常见的数组操作错误。
push() 方法和 pop() 方法是操作数组末尾元素最常用的两种方法。
arr.push(元素1, 元素2)。undefined。同样会修改原数组。|let stack = []; // 使用 push 添加元素 stack.push('A'); stack.push('B'); console.log("添加后:", stack); // 使用 pop 移除元素 let removed = stack.pop(); console.log("移除的元素:", removed); console.log("移除后:", stack);
|添加后: [ 'A', 'B' ] 移除的元素: B 移除后: [ 'A' ]
unshift() 方法用于在数组的开头插入一个或多个元素,所有原有元素的索引会依次向后移动。例如,arr.unshift('a') 会将 'a' 添加到数组最前面。 shift() 方法则用于移除数组的第一个元素,并返回被移除的元素,其余元素的索引会依次向前移动。 由于这两种操作每次都需要移动数组中的所有元素,因此在数组较大或频繁操作的场景下,可能会带来性能开销,建议在性能敏感的应用中谨慎使用。
|let queue = ['任务2', '任务3']; // 使用 unshift 在开头添加 queue.unshift('任务1'); console.log("添加后:", queue); // 使用 shift 从开头移除 let currentTask = queue.shift(); console.log("处理的任务:", currentTask); console.log("剩余任务:", queue);
|添加后: [ '任务1', '任务2', '任务3' ] 处理的任务: 任务1 剩余任务: [ '任务2', '任务3' ]
splice() 方法是数组操作中最强大和灵活的方法之一。它可以对数组进行"原地"修改,支持以下三种主要操作:
arr.splice(2, 1) 会从索引 2 开始删除 1 个元素。arr.splice(1, 0, '新元素') 会在索引 1 处插入 '新元素',原有元素向后移动。arr.splice(3, 2, 'A', 'B') 会从索引 3 开始删除 2 个元素,并插入 'A' 和 'B'。|let letters = ['a', 'b', 'c', 'd', 'e']; // 删除: 从索引2开始删除2个元素 let deleted = letters.splice(2, 2); console.log("删除后:", letters); console.log("被删除的元素:", deleted); // 插入: 在索引1处插入 'x', 'y' letters.splice(1
|删除后: [ 'a', 'b', 'e' ] 被删除的元素: [ 'c', 'd' ] 插入后: [ 'a', 'x', 'y', 'b', 'e' ] 替换后: [ 'a', 'x', 'z', 'b', 'e' ]
遍历数组是数组操作中最基础也是最重要的技能之一。在JavaScript中,数组遍历的方法非常丰富,主要包括以下几类:
for循环是最基础、最常用的数组遍历方法。它允许你手动设置循环的起始索引、结束条件和每次迭代的步长,因此在需要跳跃遍历、部分遍历、反向遍历或在遍历过程中动态修改数组时都非常灵活。
|let scores = [88, 95, 76]; for (let i = 0; i < scores.length; i++) { console.log(`第 ${i + 1} 项的分数是: ${scores[i]}`); }
|第 1 项的分数是: 88 第 2 项的分数是: 95 第 3 项的分数是: 76
for...of循环是ES6(ECMAScript 2015)引入的一种新的遍历语法。它专门用于遍历可迭代对象(如数组、字符串、Set、Map等),语法简洁,易于阅读。
|let tools = ['Hammer', 'Wrench', 'Screwdriver']; for (const tool of tools) { console.log("工具:", tool); }
|工具: Hammer 工具: Wrench 工具: Screwdriver
forEach() 方法是数组遍历的现代化选择。与传统的 for 或 for...of 循环相比,forEach() 会将每个元素的处理逻辑作为回调函数传递进来,这样可以让遍历过程更加清晰、简洁。
|const colors = ['red', 'green', 'blue']; colors.forEach(function(color, index) { console.log(`索引 ${index}: ${color}`); });
|索引 0: red 索引 1: green 索引 2: blue
在实际开发中,数组的搜索和排序是非常常见且重要的操作。为此,JavaScript 提供了多种内置方法,如 indexOf、includes、find、filter、sort 等。
在日常开发中,我们经常需要在数组中查找特定的数据。JavaScript 提供了多种强大的数组搜索方法,例如 indexOf、includes 用于基础类型的查找,find、findIndex、filter 等方法则可以根据自定义条件在对象数组中进行复杂搜索。
|let numbers = [10, 20, 30, 40, 50, 30]; let users = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}]; // indexOf: 查找值的索引 console.log("30的索引:", numbers.indexOf(30)); // includes: 检查是否包含某个值 console.log
|30的索引: 2 是否包含20: true 找到的用户: { id: 2, name: 'Bob' } 所有30: [ 30, 30 ]
数组排序是数据处理中的另一个重要操作。JavaScript 提供了内置的 sort() 方法来实现这一功能。sort() 方法不仅可以对简单类型(如数字、字符串)排序,还可以通过自定义比较函数,对对象数组按照某个属性进行复杂排序。
|let numbers = [4, 2, 5, 1, 3]; let students = [ { name: "Bob", age: 22 }, { name: "Alice", age: 20 } ]; // 数字升序排序 numbers.sort((a, b) => a - b);
|数字升序: [ 1, 2, 3, 4, 5 ] 按年龄排序: [ { name: 'Alice', age: 20 }, { name: 'Bob', age: 22 } ]
数组转换是函数式编程的核心概念之一。在JavaScript中,我们可以使用多种内置方法(如map、filter、reduce等)对数组进行灵活的转换和处理。
map()方法是最常用的数组转换方法。它会遍历原数组中的每一个元素,并对每个元素执行一次指定的回调函数,将回调函数的返回值组成一个新的数组。
|const numbers = [1, 4, 9]; const roots = numbers.map(num => Math.sqrt(num)); console.log("平方根数组:", roots);
|平方根数组: [ 1, 2, 3 ]
filter() 方法会遍历原数组,对每个元素执行你提供的回调函数(测试函数),并将所有使回调返回 true 的元素收集到一个新数组中。
|const words = ['spray', 'limit', 'elite', 'exuberant']; const longWords = words.filter(word => word.length > 5); console.log("长单词:", longWords);
|长单词: [ 'spray', 'exuberant' ]
reduce() 方法是 JavaScript 数组中最强大、最灵活的处理方法之一。它会遍历数组中的每一项,将其与累加器(上一次归约的结果)进行处理,最终"归约"为一个单一的值。
|const numbers = [1, 2, 3, 4]; const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); console.log("数组总和:", sum);
|数组总和: 10
虽然JavaScript本身并没有内置真正意义上的多维数组类型,但我们可以通过在数组中嵌套数组的方式,灵活地模拟和操作二维、三维甚至更高维度的数据结构。
|// 创建二维数组:学生成绩表 let gradeMatrix = [ ['姓名', '数学', '英语'], ['张三', 92, 78], ['李四', 88, 85] ]; // 访问二维数组元素 console.log("李四的数学成绩:", gradeMatrix[2][1]); // 遍历二维数组 gradeMatrix.
|李四的数学成绩: 88 姓名 数学 英语 张三 92 78 李四 88 85
在 JavaScript 中,除了标准的 Array 实例(即真正的数组对象),还存在一些"类数组对象"(array-like object)。这些对象虽然不是 Array 类型,但它们拥有一组连续的以数字为键的属性(如 0、1、2……),并且具有 length 属性,表现得很像数组。
|// 函数的 arguments 对象是一个类数组对象 function printArgs() { console.log("arguments对象:", arguments); // 转换为真数组来使用数组方法 const argsArray = Array.from(arguments); console.log("转换后的数组:", argsArray); argsArray.forEach(arg => console.log("参数:", arg)); } printArgs
|arguments对象: { '0': 'a', '1': 'b', '2': 'c' } 转换后的数组: [ 'a', 'b', 'c' ] 参数: a 参数: b 参数: c 字符串长度: 5 第一个字符: h 字符数组: [ 'h', 'e', 'l', 'l', 'o' ]
|let numbers = [1, 2, 3, 4, 5]; // 在末尾添加元素6 numbers._______(6); // 在开头添加元素0 numbers._______(0); // 删除最后一个元素 let last = numbers._______(); // 删除第一个元素 let first = numbers._______
|let numbers = [1, 2, 3, 4, 5]; // 在末尾添加元素6 numbers.push(6); // 在开头添加元素0 numbers.unshift(0); // 删除最后一个元素 let last = numbers.pop(); // 删除第一个元素 let first = numbers.shift
|let scores = [85, 92, 78, 96, 88]; // 找出所有大于85的分数 let highScores = scores._______(score => score > 85); // 将所有分数乘以1.1 let boostedScores = scores._______(score => score * 1.1); // 计算总分
|let scores = [85, 92, 78, 96, 88]; // 找出所有大于85的分数 let highScores = scores.filter(score => score > 85); console.log(highScores); // [92, 96, 88] // 将所有分数乘以1.1 let boostedScores = scores.map(score => score
|let fruits = ['苹果', '香蕉', '橘子', '葡萄']; // 查找'香蕉'的索引 let index = fruits._______('香蕉'); // 检查是否包含'橘子' let hasOrange = fruits._______('橘子'); // 找到第一个长度为2的水果 let shortFruit = fruits._______(fruit => fruit.
|let fruits = ['苹果', '香蕉', '橘子', '葡萄']; // 查找'香蕉'的索引 let index = fruits.indexOf('香蕉'); console.log(index); // 1 // 检查是否包含'橘子' let hasOrange = fruits.includes('橘子'); console.log(hasOrange); // true // 找到第一个长度为2的水果
|let numbers = [3, 1, 4, 1, 5, 9, 2, 6]; // 升序排列 let ascending = numbers._______((a, b) => a - b); // 反转数组 let reversed = numbers._______();
|let numbers = [3, 1, 4, 1, 5, 9, 2, 6]; // 升序排列(注意:sort会修改原数组) let ascending = [...numbers].sort((a, b) => a - b); console.log(ascending); // [1, 1, 2, 3, 4, 5, 6, 9]
|<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>学生成绩管理系统</title> </head> <body> <script> // 学生信息数组 let students = [ { name: "张三"
数组的基本操作方法:
push():在数组末尾添加元素unshift():在数组开头添加元素pop():删除并返回数组最后一个元素shift():删除并返回数组第一个元素数组的高阶方法:
filter():筛选满足条件的元素,返回新数组map():对每个元素执行操作,返回新数组reduce():累积计算,返回一个值数组搜索方法:
indexOf():查找元素的索引,找不到返回-1includes():检查数组是否包含某个元素,返回布尔值find():查找第一个满足条件的元素,返回该元素数组的排序和转换方法:
sort():排序数组,会修改原数组。使用[...numbers]创建副本避免修改原数组reverse():反转数组,会修改原数组join():将数组元素连接成字符串这个例子综合运用了: