Skip to content

ES6 - 数组

在 JavaScript 中,数组(array)是一种特殊类型的对象(object),用于存储有序的多值集合。这些值被称为元素(elements),可以是任何数据类型(数字、字符串、对象、其他数组等)。JavaScript 数组是零索引(zero-indexed)的,这意味着第一个元素位于索引 0。

  • 标量变量(Scalar variables)一次只能存储一个值。存储许多相关值需要许多独立的变量。
  • 管理和操作大量独立变量可能很麻烦。

数组通过提供一种结构化的方式来存储和管理数据列表,解决了这些问题。

  • 有序集合(Ordered Collection): 元素以特定的顺序存储,并且可以通过它们的数字索引访问。
  • 动态大小(Dynamic Size): JavaScript 数组可以动态增长或缩小;你不需要事先指定它们的大小。
  • 异构元素(Heterogeneous Elements): 数组可以存储不同数据类型的元素(尽管为了可预测性,通常最好保持元素的类型相似)。
  • 零索引(Zero-Indexed): 第一个元素位于索引 0,第二个位于索引 1,依此类推。
  • 基于对象(Object-Based): 数组是一种特殊类型的对象,Array.prototype 提供了许多有用的方法(methods)。

创建数组最常见的方式是使用数组字面量 []:

// 数组字面量语法
const emptyArray = [];
const fruits = ["Apple", "Banana", "Cherry"];
const numbers = [1, 2, 3, 4, 5];
const mixedArray = [10, "Hello", true, { name: "John" }, [6, 7]];
console.log(fruits[0]); // Apple
console.log(numbers.length); // 5

或者,你可以使用 Array 构造函数:

// 使用 Array 构造函数
const arr1 = new Array(); // 创建一个空数组,等同于 []
const arr2 = new Array(5); // 创建一个长度为 5 的数组,但元素是空的/undefined
console.log(arr2.length); // 5
console.log(arr2[0]); // undefined
const arr3 = new Array("Red", "Green", "Blue"); // 创建一个包含指定元素的数组
console.log(arr3); // ["Red", "Green", "Blue"]
// 注意:如果 new Array() 以单个数字参数调用,它会创建一个该长度的数组,
// 而不是一个包含该数字的数组。这可能导致混淆。
// 为了清晰起见,通常首选数组字面量 []。

使用方括号中的索引来访问元素。你也可以通过这种方式修改元素。

const colors = ["Red", "Green", "Blue"];
// 访问元素
console.log(colors[0]); // "Red"
console.log(colors[2]); // "Blue"
console.log(colors[3]); // undefined (索引超出范围)
// 修改元素
colors[1] = "Yellow";
console.log(colors); // ["Red", "Yellow", "Blue"]
// 通过赋值给新索引来添加元素
colors[3] = "Purple";
console.log(colors); // ["Red", "Yellow", "Blue", "Purple"]
// `length` 属性表示元素的数量。
console.log(colors.length); // 4

常用数组方法 (来自 Array.prototype)

Section titled “常用数组方法 (来自 Array.prototype)”

JavaScript 提供了一系列丰富的内置方法用于数组操作:

方法描述
push(item1, ..., itemN)将一个或多个元素添加到数组的末尾,并返回新的长度。
pop()移除数组的最后一个元素,并返回该元素。
shift()移除数组的第一个元素,并返回该元素(其他元素向前移动)。
unshift(item1, ..., itemN)将一个或多个元素添加到数组的开头,并返回新的长度。
concat(array2, ..., arrayN)返回一个新数组,其中包含当前数组与其他数组和/或值连接后的元素。不修改原始数组。
join(separator)将数组的所有元素连接成一个字符串,元素之间用指定的 separator(默认为逗号)分隔。
slice(startIndex, endIndex)返回数组的一部分的浅拷贝(shallow copy)到新数组对象中。不包含 endIndex。不修改原始数组。
splice(startIndex, deleteCount, item1, ..., itemN)通过在原数组中移除、替换或添加元素来改变数组内容。修改原始数组,并返回一个包含已删除元素的数组。
indexOf(searchElement, fromIndex)返回给定元素在数组中第一次出现的索引,如果不存在则返回 -1。
lastIndexOf(searchElement, fromIndex)返回给定元素在数组中最后一次出现的索引,从后向前搜索。
includes(searchElement, fromIndex) (ES2016)判断数组是否包含某个值,返回 true 或 false。
sort(compareFunction)在原数组中对元素进行排序。默认按元素转换为字符串后的 UTF-16 码单元值排序。提供 compareFunction 用于自定义排序(例如,对数字排序)。
reverse()在原数组中颠倒元素的顺序。
  • forEach(callback(element, index, array)): 对数组中的每个元素执行一次提供的函数。
  • map(callback(element, index, array)): 创建一个新数组,其中包含对原数组中的每个元素调用提供的函数后的结果。
  • filter(callback(element, index, array)): 创建一个新数组,其中包含通过提供的函数实现的测试的所有元素。
  • reduce(callback(accumulator, currentValue, currentIndex, array), initialValue): 对数组中的每个元素执行一个 reducer 函数,最终产生一个单一的输出值。
  • reduceRight(...): 类似于 reduce(),但从右到左处理数组。
  • some(callback(element, index, array)): 测试数组中是否至少有一个元素通过了提供的函数实现的测试。
  • every(callback(element, index, array)): 测试数组中的所有元素是否都通过了提供的函数实现的测试。
  • for...of 循环 (ES6): 遍历可迭代对象(iterable object,如数组)的值。这通常是循环遍历数组值最直接的方式。
const myNumbers = [10, 20, 30];
// Using forEach
myNumbers.forEach(function(number, index) {
console.log(`forEach: Element at index ${index} is ${number}`);
});
// Using for...of (simpler for just values)
for (const number of myNumbers) {
console.log(`for...of: Element is ${number}`);
}
// Note: `for...in` loop should generally NOT be used to iterate over arrays, as it iterates over enumerable properties (including array indices and potentially inherited properties) and gives indices as strings. Use `for...of` or `forEach` for array values.
  • Array.from(arrayLikeOrIterable, mapFn, thisArg): 从类数组(array-like)或可迭代(iterable)对象(例如,NodeList、String、Set、Map)创建一个新的、浅拷贝的 Array 实例。
  • Array.of(...elements): 创建一个带有可变数量参数的新 Array 实例,无论参数的数量或类型如何(对于单个数字参数比 new Array() 更安全)。
  • find(callback(element, index, array)): 返回数组中第一个满足提供的测试函数的元素。如果没有值满足测试函数,则返回 undefined。
  • findIndex(callback(element, index, array)): 返回数组中第一个满足提供的测试函数的元素的索引。否则,返回 -1。
  • entries(): 返回一个新的 Array Iterator 对象,其中包含数组中每个索引的键/值对。
  • keys(): 返回一个新的 Array Iterator 对象,其中包含数组中每个索引的键(索引)。
  • values(): 返回一个新的 Array Iterator 对象,其中包含数组中每个索引的值。
  • 扩展语法 (...): 可以用于将可迭代对象(如数组)扩展为单独的元素。对于创建副本、连接数组或将元素作为函数参数传递很有用。
  • 解构赋值(Destructuring Assignment): 允许将数组中的值解包到不同的变量中。
// Array.from a string
const nameChars = Array.from('Hello');
console.log(nameChars); // ['H', 'e', 'l', 'l', 'o']
// Array.of
const singleNumArray = Array.of(7);
console.log(singleNumArray); // [7]
// find and findIndex
const inventory = [
{ name: 'apples', quantity: 2 },
{ name: 'bananas', quantity: 0 },
{ name: 'cherries', quantity: 5 }
];
const cherryItem = inventory.find(item => item.name === 'cherries');
console.log(cherryItem); // { name: 'cherries', quantity: 5 }
const bananaIndex = inventory.findIndex(item => item.name === 'bananas');
console.log(bananaIndex); // 1
// entries, keys, values (using for...of with iterator)
const letters = ['a', 'b', 'c'];
for (const [index, value] of letters.entries()) {
console.log(`Index: ${index}, Value: ${value}`);
}
// Output: Index: 0, Value: a ... etc.
// Spread Syntax
const arrA = [1, 2];
const arrB = [3, 4];
const combined = [...arrA, 0, ...arrB, 5];
console.log(combined); // [1, 2, 0, 3, 4, 5]
const copyArrA = [...arrA]; // Shallow copy
// Destructuring Assignment
const [first, second, , fourth] = [10, 20, 30, 40];
console.log(first); // 10
console.log(second); // 20
console.log(fourth); // 40 (30 is skipped)

JavaScript 没有像 C++/Java 那样的真正的多维数组,但你可以通过创建数组的数组来实现类似的功能。

const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
console.log(matrix[0][0]); // 1 (第一行,第一列)
console.log(matrix[1][2]); // 6 (第二行,第三列)

数组是 JavaScript 数据处理的基石,为各种任务提供了灵活性和一套强大的方法。