JavaScript数组从入门到精通:常用方法详解+实战示例|10年开发经验总结

大家好,我是第八哥,一名有 10 年互联网开发经验的老兵。今天跟大伙儿好好聊聊JavaScript数组,这玩意儿在JS里太重要了,不管是新手入门还是老手进阶,都绕不开它。

一、JavaScript数组基础:从创建到访问

先说说数组是啥。简单来说,就是用方括号把一堆数据括起来,数据之间用逗号隔开。比如存几个名字的数组可以这样写:

let names = ['Alice''Bob''John'];

那么如何访问数组里的元素呢?用索引就行了,记住索引是从0开始的。比如取第一个元素可以这样写:

console.log(names[0]); // 控制台就会输出'Alice'

二、数组增删元素:push、pop、shift、unshift

push:在数组末尾添加一个或多个元素,并返回添加后的数组长度。
比如给names数组加个'Jane':

let len = names.push('Jane');
console.log(names); // 输出 ['Alice', 'Bob', 'John', 'Jane']
console.log(len); // 输出数组的长度 4

或者一次性添加多个元素:

let len = names.push('Charlie''Jane');
console.log(names); // ['Alice', 'Bob', 'John', 'Charlie', 'Jane']
console.log(len); // 5

pop:删除数组的最后一个元素,并返回被删除的元素。

let tmp = names.pop(); // 删除数组中的 Jane
console.log(names); // ['Alice', 'Bob', 'John']
console.log(tmp); // Jane

注意:如果对空数组使用pop会返回undefined

unshift:在数组开头添加一个或多个元素,并返回添加后的数组长度。

let len = names.unshift('Ada');
console.log(names); // 输出 ['Ada', 'Alice', 'Bob', 'John']
console.log(len); // 输出数组的长度 4

或者一次添加多个:

let len = names.push('Ada''Mary');
console.log(names); // ['Ada', 'Mary', 'Alice', 'Bob', 'John']
console.log(len); // 5

shift:删除数组的第一个元素,并返回被删除的元素。

let tmp = names.shift(); // 删除数组中的 Ada
console.log(names); // ['Alice', 'Bob', 'John']
console.log(tmp); // Ada

注意:对于空数组,和pop方法一样,都会返回undefined

在实际开发中,优先推荐使用push/pop而不是shift/unshift,因为前者性能更好,时间复杂度为O(1),而后者的时间复杂度为O(n)。对于大型数组要避免频繁的使用shift/unshift,考虑改用其他数据结构。

三、数组遍历:forEach、map、filter

forEach:遍历数组中的每个元素并执行回调函数,无法使用 breakreturn 中断循环。
比如:遍历数组names,打印数组中的每一个元素及对应的索引值。

names.forEach(function (name, index) {
    console.log(`索引 ${index} 的值是 ${name}`);
});

// 或者使用箭头函数
names.forEach((name, index) => console.log(`索引 ${index} 的值是 ${name}`));

forEach的回调参数提供(item, index, array)三个参数,方便访问元素信息。

map:遍历数组并返回一个新数组,新数组由回调函数的返回值组成,新数组的长度与原数组相同。

// 给数组中的每个元素前面添加 Hello
let students = names.map(name => 'Hello ' + name);
console.log(students); // ['Hello Alice', 'Hello Bob', 'Hello John']

// 或者转换为对象数组
let objStus = names.map((name, id) => ({
  id: id + 1,
  name: name
}));
console.log(objStus);

对于大数据量转换考虑Web Worker或分批处理。

filter:根据条件筛选数组元素,返回符合条件的新数组,新数组长度可能小于原数组。

let tmp = names.filter(name => name.includes('o'));
console.log(tmp); // ['Bob', 'John']

复杂的条件可拆分为多个filter调用或提取为独立函数,配合Boolean构造函数可快速过滤假值。

四、数组转换与合并:join、concat、slice

join:将数组中的所有元素连接成一个字符串;不改变原数组;如果是空数组则返回的是空字符串。

let fruits = ['apple''banana''orange'];

// 默认用逗号连接
console.log(fruits.join()); // "apple,banana,orange"

// 自定义分隔符
console.log(fruits.join('-')); // "apple-banana-orange"

// 空分隔符
console.log(fruits.join('')); // "applebananaorange"

当需要将大型数组转换为字符串时,join()比循环拼接字符串性能更好;数组中的null和undefined会被转换为空字符串。

concat:合并多个数组或值;返回新数组,原数组不变;可以接受数组或非数组参数。

let arr1 = [12];
let arr2 = [34];

// 合并两个数组
let combined = arr1.concat(arr2);
console.log(combined); // [1, 2, 3, 4]

// 合并数组和值
let withValues = arr1.concat(5, [67]);
console.log(withValues); // [1, 2, 5, 6, 7]

// 多层数组会展开一层
let nested = arr1.concat([8, [910]]);
console.log(nested); // [1, 2, 8, [9, 10]]

concat只复制数组引用,不深度复制对象元素;在连接大型数组时,考虑使用扩展运算符(...)可能更高效。

slice:截取数组或字符串‌,返回数组或字符串‌的浅拷贝部分;不改变原数组或字符串‌。

let numbers = [012345];

// 获取索引1到3(不包括3)的元素
console.log(numbers.slice(13)); // [1, 2]

// 从索引2开始到结束
console.log(numbers.slice(2)); // [2, 3, 4, 5]

// 复制整个数组
console.log(numbers.slice()); // [0, 1, 2, 3, 4, 5]

// 负索引表示从末尾开始
console.log(numbers.slice(-3)); // [3, 4, 5]

slice的第一个参数是起始索引(包含),第二个是结束索引(不包含);支持负数索引,表示从末尾开始计算。

五、数组高级用法:reduce

reduce 通过迭代处理数组元素并将结果累积为单个值,不仅可以用来进行数值计算,还能做复杂处理,比如统计元素出现次数、数据转换、数据分组等,只要灵活运用回调函数就行。

数值计算

// 数组求和,0为累积器acc的初始值,如果不提供,则首次调用回调时acc的值为数组的第一个元素的值
[123].reduce((acc, cur) => acc + cur, 0); // 6

// 求最大值
[83115].reduce((max, num) => Math.max(max, num)); // 11

数据转换

// 数组转对象
[['name''Alice'], ['age'30]].reduce((obj, [key, val]) => {
    obj[key] = val;
    return obj;
}, {}); // {name: 'Alice', age: 30}

// 扁平化二维数组
[[12], [34]].reduce((flat, arr) => flat.concat(arr), []); // [1,2,3,4]

数据聚合

// 统计元素频率
['apple''banana''apple'].reduce((count, fruit) => {
    count[fruit] = (count[fruit] || 0) + 1;
    return count;
}, {}); // {apple: 2, banana: 1}

// 分组数据
const people = [
    { name'Alice'dept'HR' },
    { name'Bob'dept'IT' },
    { name'John'dept'IT' },
    { name'Jane'dept'HR' }
];
people.reduce((groups, person) => {
    const dept = person.dept;
    groups[dept] = groups[dept] || [];
    groups[dept].push(person);
    return groups;
}, {});

掌握这些方法,对付日常开发里的数组操作基本没什么问题了。多写多练,很快就能熟练。要是有疑问,欢迎留言交流~

上一篇 JavaScript调试技巧大全:从控制台到Source Map,快速定位问题提升开发效率的进阶指南 下一篇 JavaScript Map 完全指南:从基础入门到精通实战 | 详细解析与示例代码

评论

暂不支持评论