数组是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
访问空槽: undefinedJavaScript 提供了多种方法来添加和删除数组元素,常见的有 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 项的分数是: 76for...of循环是ES6(ECMAScript 2015)引入的一种新的遍历语法。它专门用于遍历可迭代对象(如数组、字符串、Set、Map等),语法简洁,易于阅读。
let tools = ['Hammer', 'Wrench', 'Screwdriver'];
for (const tool of tools) {
console.log("工具:", tool);
}工具: Hammer
工具: Wrench
工具: ScrewdriverforEach() 方法是数组遍历的现代化选择。与传统的 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():将数组元素连接成字符串这个例子综合运用了: