JavaScript 数组学习总结

JavaScript 数组学习总结

JavaScript 数组是一种特殊的对象,用于存储有序的数据集合。它是 JavaScript 中最常用的数据结构之一,提供了丰富的内置方法来处理数据。以下是对 JavaScript 数组的全面总结:

一、数组基础

1. 数组的定义与创建

数组可以通过多种方式创建:

javascript

复制代码
// 1. 数组字面量(最常用)
const fruits = ["苹果", "香蕉", "橙子"];
const mixed = [1, "字符串", true, null, { name: "对象" }];

// 2. 使用 Array 构造函数
const numbers = new Array(1, 2, 3, 4, 5);
const emptyArray = new Array(5); // 创建长度为 5 的空数组

// 3. Array.of() 方法(ES6)
const arrayOf = Array.of(1, 2, 3); // [1, 2, 3]
const singleElement = Array.of(5); // [5],区别于 new Array(5)

// 4. Array.from() 方法(ES6)- 从类数组或可迭代对象创建数组
const fromString = Array.from("hello"); // ['h', 'e', 'l', 'l', 'o']
const fromSet = Array.from(new Set([1, 2, 2, 3])); // [1, 2, 3]
const fromMap = Array.from(new Map([[1, 'a'], [2, 'b']])); // [[1, 'a'], [2, 'b']]

// 使用映射函数
const doubled = Array.from([1, 2, 3], x => x * 2); // [2, 4, 6]

2. 数组的基本特性

javascript

复制代码
// 数组是对象的一种特殊形式
console.log(typeof fruits); // "object"
console.log(Array.isArray(fruits)); // true

// 数组长度
console.log(fruits.length); // 3

// 访问数组元素
console.log(fruits[0]); // "苹果"
console.log(fruits[fruits.length - 1]); // "橙子"

// 修改数组元素
fruits[1] = "葡萄";
console.log(fruits); // ["苹果", "葡萄", "橙子"]

// 添加元素
fruits[3] = "西瓜";
console.log(fruits); // ["苹果", "葡萄", "橙子", "西瓜"]

// 稀疏数组
const sparse = [];
sparse[10] = 10;
console.log(sparse.length); // 11
console.log(sparse); // [empty × 10, 10]

二、数组方法

1. 修改原数组的方法(破坏性方法)

javascript

复制代码
// push() - 在数组末尾添加一个或多个元素,并返回新的长度
const length = fruits.push("草莓", "蓝莓");
console.log(fruits); // ["苹果", "葡萄", "橙子", "西瓜", "草莓", "蓝莓"]
console.log(length); // 6

// pop() - 移除并返回数组的最后一个元素
const last = fruits.pop();
console.log(fruits); // ["苹果", "葡萄", "橙子", "西瓜", "草莓"]
console.log(last); // "蓝莓"

// shift() - 移除并返回数组的第一个元素
const first = fruits.shift();
console.log(fruits); // ["葡萄", "橙子", "西瓜", "草莓"]
console.log(first); // "苹果"

// unshift() - 在数组开头添加一个或多个元素,并返回新的长度
const newLength = fruits.unshift("猕猴桃", "菠萝");
console.log(fruits); // ["猕猴桃", "菠萝", "葡萄", "橙子", "西瓜", "草莓"]
console.log(newLength); // 6

// splice() - 从数组中添加/删除元素,返回被删除的元素
// splice(start, deleteCount, itemsToAdd)
const removed = fruits.splice(2, 2, "芒果", "荔枝");
console.log(fruits); // ["猕猴桃", "菠萝", "芒果", "荔枝", "西瓜", "草莓"]
console.log(removed); // ["葡萄", "橙子"]

// reverse() - 反转数组中元素的顺序
fruits.reverse();
console.log(fruits); // ["草莓", "西瓜", "荔枝", "芒果", "菠萝", "猕猴桃"]

// sort() - 对数组元素进行排序(默认按字符串比较)
const numbers = [5, 3, 8, 1, 2];
numbers.sort();
console.log(numbers); // [1, 2, 3, 5, 8]

// 自定义排序函数
const people = [
  { name: "张三", age: 25 },
  { name: "李四", age: 20 },
  { name: "王五", age: 30 }
];

people.sort((a, b) => a.age - b.age);
console.log(people); // 按年龄升序排列

// fill() - 用一个固定值填充数组中从起始索引到终止索引内的全部元素
const filled = [1, 2, 3, 4, 5].fill(0, 2, 4);
console.log(filled); // [1, 2, 0, 0, 5]

2. 返回新数组的方法(非破坏性方法)

javascript

复制代码
// slice() - 返回数组的一部分浅拷贝
const sliced = fruits.slice(1, 3);
console.log(sliced); // ["西瓜", "荔枝"]
console.log(fruits); // 原数组不变

// concat() - 合并多个数组,返回新数组
const moreFruits = ["香蕉", "樱桃"];
const combined = fruits.concat(moreFruits);
console.log(combined); // ["草莓", "西瓜", "荔枝", "芒果", "菠萝", "猕猴桃", "香蕉", "樱桃"]

// join() - 将数组元素连接成字符串
const joined = fruits.join(", ");
console.log(joined); // "草莓, 西瓜, 荔枝, 芒果, 菠萝, 猕猴桃"

// split() - 字符串方法,将字符串分割成数组
const words = "Hello,World,JavaScript".split(",");
console.log(words); // ["Hello", "World", "JavaScript"]

// map() - 创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果
const doubled = [1, 2, 3].map(num => num * 2);
console.log(doubled); // [2, 4, 6]

// filter() - 创建一个新数组,包含通过所提供函数实现的测试的所有元素
const evenNumbers = [1, 2, 3, 4, 5].filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4]

// reduce() - 对数组中的每个元素执行一个由您提供的reducer函数,将其结果汇总为单个返回值
const sum = [1, 2, 3, 4, 5].reduce((acc, num) => acc + num, 0);
console.log(sum); // 15

// 计算数组中每个元素出现的次数
const countOccurrences = ["a", "b", "a", "c", "b", "a"].reduce((acc, item) => {
  acc[item] = (acc[item] || 0) + 1;
  return acc;
}, {});
console.log(countOccurrences); // {a: 3, b: 2, c: 1}

// flat() - 创建一个新数组,所有子数组元素递归地连接到该数组中
const nested = [1, [2, [3]]];
const flattened = nested.flat(2); // 深度为 2
console.log(flattened); // [1, 2, 3]

// flatMap() - 首先使用映射函数映射每个元素,然后将结果压缩成一个新数组
const sentences = ["Hello world", "I love JavaScript"];
const words = sentences.flatMap(sentence => sentence.split(" "));
console.log(words); // ["Hello", "world", "I", "love", "JavaScript"]

3. 查找和判断方法

javascript

复制代码
// indexOf() - 返回在数组中可以找到给定元素的第一个索引,如果不存在,则返回-1
const index = fruits.indexOf("芒果");
console.log(index); // 3

// lastIndexOf() - 返回指定元素在数组中的最后一个的索引,如果不存在则返回-1
const lastIndex = fruits.lastIndexOf("芒果");
console.log(lastIndex); // 3

// includes() - 判断一个数组是否包含一个指定的值
const hasMango = fruits.includes("芒果");
console.log(hasMango); // true

// find() - 返回数组中满足提供的测试函数的第一个元素的值
const person = people.find(p => p.age > 20);
console.log(person); // { name: "张三", age: 25 }

// findIndex() - 返回数组中满足提供的测试函数的第一个元素的索引
const personIndex = people.findIndex(p => p.age > 20);
console.log(personIndex); // 0

// every() - 测试一个数组内的所有元素是否都能通过某个指定函数的测试
const allAdults = people.every(p => p.age >= 18);
console.log(allAdults); // true

// some() - 测试数组中是不是至少有1个元素通过了被提供的函数测试
const hasYoungPerson = people.some(p => p.age < 25);
console.log(hasYoungPerson); // true

4. 迭代方法

javascript

复制代码
// forEach() - 对数组的每个元素执行一次提供的函数
fruits.forEach(fruit => {
  console.log(fruit);
});

// for...of 循环(ES6)
for (const fruit of fruits) {
  console.log(fruit);
}

// for...in 循环(不推荐用于数组)
for (const index in fruits) {
  console.log(fruits[index]);
}

三、数组排序

1. 默认排序

javascript

复制代码
// 默认按字符串 Unicode 编码排序
const mixed = [10, 1, 2, "10", "2", "a", "A"];
mixed.sort();
console.log(mixed); // ['10', 1, 10, '2', 2, 'A', 'a']

2. 自定义排序

javascript

复制代码
// 数字排序
const numbers = [5, 3, 8, 1, 2];
numbers.sort((a, b) => a - b); // 升序
console.log(numbers); // [1, 2, 3, 5, 8]

numbers.sort((a, b) => b - a); // 降序
console.log(numbers); // [8, 5, 3, 2, 1]

// 字符串排序(不区分大小写)
const words = ["banana", "Apple", "cherry"];
words.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
console.log(words); // ["Apple", "banana", "cherry"]

// 对象排序
const products = [
  { name: "手机", price: 3000 },
  { name: "电脑", price: 5000 },
  { name: "平板", price: 2000 }
];

// 按价格升序
products.sort((a, b) => a.price - b.price);
console.log(products);

四、数组与字符串的转换

1. 数组转字符串

javascript

复制代码
const arr = ["a", "b", "c"];

// join() 方法
const joined = arr.join(); // "a,b,c"
const customJoined = arr.join("-"); // "a-b-c"

// toString() 方法
const str = arr.toString(); // "a,b,c"

2. 字符串转数组

javascript

复制代码
const str = "Hello,World";

// split() 方法
const chars = str.split(""); // ["H", "e", "l", "l", "o", ",", "W", "o", "r", "l", "d"]
const words = str.split(","); // ["Hello", "World"]

// ES6 扩展运算符
const chars2 = [...str]; // ["H", "e", "l", "l", "o", ",", "W", "o", "r", "l", "d"]

五、数组的高级应用

1. 多维数组

javascript

复制代码
// 创建二维数组
const matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

// 访问多维数组元素
console.log(matrix[1][2]); // 6

// 二维数组转一维数组
const flattened = matrix.flat(); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

// 遍历多维数组
matrix.forEach(row => {
  row.forEach(cell => {
    console.log(cell);
  });
});

2. 数组去重

javascript

复制代码
// 使用 Set(ES6)
const duplicates = [1, 2, 2, 3, 3, 3];
const unique = [...new Set(duplicates)];
console.log(unique); // [1, 2, 3]

// 使用 filter() 方法
const unique2 = duplicates.filter((value, index, self) => {
  return self.indexOf(value) === index;
});
console.log(unique2); // [1, 2, 3]

3. 数组扁平化

javascript

复制代码
// 递归实现
function flatten(arr) {
  return arr.reduce((acc, val) => {
    return acc.concat(Array.isArray(val) ? flatten(val) : val);
  }, []);
}

const deeplyNested = [1, [2, [3, [4]]]];
console.log(flatten(deeplyNested)); // [1, 2, 3, 4]

// 使用 flat() 方法(ES6)
console.log(deeplyNested.flat(Infinity)); // [1, 2, 3, 4]

4. 数组分组

javascript

复制代码
// 根据条件分组
const numbers = [1, 2, 3, 4, 5, 6];
const grouped = numbers.reduce((acc, num) => {
  const key = num % 2 === 0 ? "偶数" : "奇数";
  if (!acc[key]) {
    acc[key] = [];
  }
  acc[key].push(num);
  return acc;
}, {});

console.log(grouped); // {奇数: [1, 3, 5], 偶数: [2, 4, 6]}

5. 数组的交集、并集和差集

javascript

复制代码
const arr1 = [1, 2, 3, 4];
const arr2 = [3, 4, 5, 6];

// 交集
const intersection = arr1.filter(value => arr2.includes(value));
console.log(intersection); // [3, 4]

// 并集
const union = [...new Set([...arr1, ...arr2])];
console.log(union); // [1, 2, 3, 4, 5, 6]

// 差集(arr1 中独有的元素)
const difference = arr1.filter(value => !arr2.includes(value));
console.log(difference); // [1, 2]

六、性能考虑

  1. 访问元素:数组的随机访问性能非常好,时间复杂度为 O (1)
  2. 添加 / 删除元素
    • 在数组末尾添加 / 删除元素(push/pop):O (1)
    • 在数组开头添加 / 删除元素(unshift/shift):O (n),需要移动所有元素
    • 在数组中间添加 / 删除元素(splice):O (n)
  3. 迭代方法
    • for 循环通常比 forEach、map 等方法快
    • for...of 循环比 for...in 循环性能更好
  4. 大数组操作:处理大数组时,注意内存使用和性能问题
  5. 避免稀疏数组:稀疏数组会降低性能

七、注意事项

  1. 引用类型:数组是引用类型,赋值和传递时传递的是引用而非副本
  2. 深拷贝 vs 浅拷贝
    • 浅拷贝:slice()concat()、扩展运算符(...
    • 深拷贝:可以使用 JSON.parse(JSON.stringify())(但不能处理函数、RegExp 等)
  3. 类数组对象 :如 arguments、DOM 节点列表等,可以使用 Array.from() 或扩展运算符转换为数组
  4. 数组空位:避免在数组中使用空位,会导致意外行为
  5. 遍历方法的返回值
    • forEach:返回 undefined
    • map、filter、reduce 等:返回新数组或值

JavaScript 数组是一种功能强大且灵活的数据结构,掌握数组的各种方法和应用场景对于编写高效的 JavaScript 代码至关重要。合理使用数组方法可以简化代码,提高开发效率。

相关推荐
我在北京coding14 分钟前
Uncaught ReferenceError: process is not defined
前端·javascript·vue.js
张成AI17 分钟前
A2A JS SDK 完整教程:快速入门指南
javascript·agent·a2a
baozj23 分钟前
一次表单数据复用引发的 Bug:理解 Vue 中的 data 为何是函数
前端·javascript·vue.js
LRH25 分钟前
JS基础 - instanceof 理解及手写
前端·javascript
小小神仙27 分钟前
JSCommon系列 - 为什么前端没有 Apache Commons?
前端·javascript·设计模式
一头小鹿28 分钟前
【JS】手写显示绑定改变this指向的方法call、apply、bind | 笔记整理
javascript
Sun_light29 分钟前
深入理解 JavaScript 对象:从入门到精通
前端·javascript
中微子29 分钟前
从零构建电影展示页面:原生js Web开发技术解析
前端·javascript
Mintopia35 分钟前
计算机图形学中的几何体布尔运算:一场形状的奇幻冒险
前端·javascript·计算机图形学
代码小将38 分钟前
java中static学习笔记
java·笔记·学习