JavaScript 数组
JavaScript 数组:存储和管理集合
Section titled “JavaScript 数组:存储和管理集合”JavaScript 数组(arrays)是灵活有序的集合,用于在单个变量中存储多个值(可以是任何类型)。它们是用于管理列表项的基本数据结构。
最常见且推荐创建数组的方法是使用数组字面量(array literal)[]:
const fruits = ["Apple", "Banana", "Cherry"];const numbers = [1, 2, 3, 4, 5];const mixedArray = ["Hello", 100, true, { name: "John" }, ["nested", "array"]];const emptyArray = [];在数组字面量中,为了提高可读性,空格和换行符并不重要:
const cars = [ "Saab", "Volvo", "BMW"];末尾逗号(例如,[1, 2, 3,])在现代 JavaScript 环境中是允许且通常安全的,但在旧版 IE 中可能存在问题。
使用 new Array()(不太常见,可能存在陷阱)
Section titled “使用 new Array()(不太常见,可能存在陷阱)”你也可以使用 Array 构造函数来创建数组:
const arr1 = new Array("Saab", "Volvo", "BMW"); // 创建一个包含这些元素的数组const arr2 = new Array(10, 20, 30);
// 陷阱:如果 new Array() 只传入一个数字参数,// 它将创建一个具有该长度(空槽)的数组,而不是一个包含该数字作为元素的数组。const arrLength5 = new Array(5); // 创建一个长度为 5 的空数组:[empty x 5]console.log(arrLength5.length); // 5console.log(arrLength5[0]); // undefined
// 要创建一个只包含一个数字元素的数组:const singleNumArr = [42]; // 推荐方式// const singleNumArrAlt = new Array(42); // 这会创建一个长度为 42 的数组!
// 为了简洁性、可读性并避免陷阱,几乎总是优先使用数组字面量 `[]`。访问数组元素
Section titled “访问数组元素”数组元素通过零基索引(zero-based indexing)访问(第一个元素位于索引 0)。
const colors = ["Red", "Green", "Blue"];
console.log(colors[0]); // 输出: "Red"console.log(colors[1]); // 输出: "Green"console.log(colors[2]); // 输出: "Blue"console.log(colors[3]); // 输出: undefined (索引越界)修改数组元素
Section titled “修改数组元素”你可以通过为其索引赋值来改变元素的值:
colors[1] = "Yellow";console.log(colors); // 输出: ["Red", "Yellow", "Blue"]数组属性和方法
Section titled “数组属性和方法”数组具有许多内置属性(properties)和方法(methods),这使得它们功能强大。
length 属性
Section titled “length 属性”length 属性返回数组中元素的数量。它总是比最高索引大一。
const numbers = [10, 20, 30, 40];console.log(numbers.length); // 输出: 4
// length 属性是可写的(writable)。// 将其设置为较小的值会截断(truncate)数组。// 将其设置为较大的值会创建稀疏(sparse)数组(空槽)。numbers.length = 2;console.log(numbers); // 输出: [10, 20]console.log(numbers.length); // 输出: 2添加和删除元素(可变方法 - Mutating Methods)
Section titled “添加和删除元素(可变方法 - Mutating Methods)”push(item1, ..., itemN): 在数组末尾添加一个或多个元素,并返回新的长度。pop(): 移除数组的最后一个元素,并返回该元素。unshift(item1, ..., itemN): 在数组开头添加一个或多个元素,并返回新的长度。shift(): 移除数组的第一个元素,并返回该元素。
const tasks = ["Write code"];tasks.push("Test code", "Deploy code"); // tasks 现在是 ["Write code", "Test code", "Deploy code"]const removedTask = tasks.pop(); // removedTask 是 "Deploy code",tasks 现在是 ["Write code", "Test code"]tasks.unshift("Plan features"); // tasks 现在是 ["Plan features", "Write code", "Test code"]const firstTask = tasks.shift(); // firstTask 是 "Plan features",tasks 现在是 ["Write code", "Test code"]splice(startIndex, deleteCount, item1, ..., itemN): 一个多用途方法,用于添加、移除或替换元素。它修改原数组,并返回一个包含被删除元素的数组。
const months = ["Jan", "March", "April", "June"];// 在索引 1 处插入 'Feb'months.splice(1, 0, "Feb");// months 现在是 ["Jan", "Feb", "March", "April", "June"]
// 将索引 3 处('April')的 1 个元素替换为 'May'months.splice(3, 1, "May");// months 现在是 ["Jan", "Feb", "March", "May", "June"]
// 移除索引 0 处的 1 个元素const deleted = months.splice(0, 1);// deleted 是 ["Jan"],months 现在是 ["Feb", "March", "May", "June"]for 循环(传统方式)
Section titled “for 循环(传统方式)”for (let i = 0; i < fruits.length; i++) { console.log(fruits[i]);}forEach(callbackFunction) (ES5+)
Section titled “forEach(callbackFunction) (ES5+)”对数组中的每个元素执行一次提供的函数(callbackFunction)。
fruits.forEach(function(fruit, index, array) { console.log(`Index ${index}: ${fruit}`);});// 使用箭头函数(arrow function):fruits.forEach((fruit, index) => console.log(`${index}: ${fruit}`));for...of 循环 (ES6) - 遍历值的首选方式
Section titled “for...of 循环 (ES6) - 遍历值的首选方式”迭代(iterate)可迭代对象(iterable objects)的值,包括数组。
for (const fruit of fruits) { console.log(fruit);}现代数组方法(非可变 - 返回新数组)
Section titled “现代数组方法(非可变 - 返回新数组)”这些方法不会改变原数组,而是返回一个新的数组或值。
map(callbackFunction): 通过对原数组的每个元素调用一个函数来创建一个新数组。filter(callbackFunction): 创建一个新数组,其中包含通过提供的函数实现的测试的所有元素。reduce(callbackFunction, initialValue): 对每个元素执行一个 reducer 函数,最终得到一个单一的输出值。slice(startIndex, endIndex): 返回数组的一部分的浅拷贝(shallow copy)到一个新数组。endIndex是不包含的。concat(array2, ..., arrayN): 合并两个或多个数组。返回一个新数组。find(callbackFunction): 返回数组中满足提供的测试函数的第一个元素。findIndex(callbackFunction): 返回数组中满足测试函数的第一个元素的索引。some(callbackFunction): 测试数组中是否至少有一个元素通过了测试。every(callbackFunction): 测试数组中是否所有元素都通过了测试。flat(depth): 创建一个新数组,并将所有子数组元素递归地连接到其中,直到达到指定的深度。flatMap(callbackFunction): 使用映射函数映射每个元素,然后将结果展平(flatten)到一个新数组(深度为 1)。
const nums = [1, 2, 3, 4, 5];const doubled = nums.map(num => num * 2); // [2, 4, 6, 8, 10]const evens = nums.filter(num => num % 2 === 0); // [2, 4]const sum = nums.reduce((accumulator, current) => accumulator + current, 0); // 15
const subArray = nums.slice(1, 3); // [2, 3]
const moreNums = [6, 7];const combined = nums.concat(moreNums); // [1, 2, 3, 4, 5, 6, 7]// 使用展开运算符(spread operator)进行合并:const combinedSpread = [...nums, ...moreNums];
const firstEven = nums.find(num => num % 2 === 0); // 2在 JavaScript 中,数组是一种特殊类型的对象。typeof 运算符对于数组返回 "object"。
console.log(typeof fruits); // 输出: "object"要可靠地检查变量是否是数组,请使用 Array.isArray():
console.log(Array.isArray(fruits)); // 输出: trueconsole.log(Array.isArray({a: 1})); // 输出: false虽然数组是对象,但它们针对数字索引访问进行了优化,而普通对象则针对命名属性进行了优化。
展开运算符(...)和数组解构(ES6)
Section titled “展开运算符(...)和数组解构(ES6)”展开运算符 (Spread Operator):
Section titled “展开运算符 (Spread Operator):”展开运算符将可迭代对象(如数组)展开为单独的元素。
const original = [1, 2, 3];const copy = [...original]; // 创建一个浅拷贝const merged = [...original, 4, 5, ...moreNums]; // 合并数组
function sumNumbers(a, b, c) { return a + b + c; }console.log(sumNumbers(...original)); // 将数组元素展开作为参数:sumNumbers(1, 2, 3)数组解构 (Array Destructuring):
Section titled “数组解构 (Array Destructuring):”允许将数组中的值解包到不同的变量中。
const [first, second, ...rest] = ["Apple", "Banana", "Cherry", "Date"];console.log(first); // "Apple"console.log(second); // "Banana"console.log(rest); // ["Cherry", "Date"] (剩余运算符(rest operator)收集剩余元素)有关数组方法的完整指南,请访问 MDN Array 文档。