深度解读JavaScript 数组以及常用方法的差异性(不知不觉高达三十几个了)希望你一次学懂

226 阅读8分钟

JavaScript 数组是一种用于存储多个值的特殊数据类型,属于对象的一种。它提供了一种有序的数据结构,可以通过索引访问其中的元素。以下是关于 JavaScript 数组的一些核心概念:

1. 数组的基本特性

  • 有序集合:数组中的元素是有序的,每个元素都有一个索引,索引从 0 开始。
  • 动态大小:JavaScript 数组的大小是动态的,可以根据需要增加或减少元素。
  • 类型混合:数组可以包含不同类型的元素,包括基本数据类型(例如数字、字符串、布尔值)和引用类型(例如对象、数组、函数)。

2. 数组的创建

  • 字面量方式

    const arr = [1, 2, 3, '四', { key: 'value' }];
    
  • 构造函数方式

    const arr = new Array(1, 2, 3);
    

3. 数组的访问

可以通过索引访问数组中的元素:

console.log(arr[0]); // 输出: 1
console.log(arr[3]); // 输出: 四

4. 数组的常用方法

JavaScript 提供了许多内置方法,用于操作数组,如:

  • 添加/删除元素push()pop()shift()unshift()splice()
  • 查找元素indexOf()find()findIndex()
  • 遍历元素forEach()map()filter()reduce()
  • 排序和反转sort()reverse()

5. 数组的原型链

JavaScript 数组是对象的一个实例,因此数组可以访问 Object 的所有方法。数组对象也有自己的方法,这些方法不在 Object 原型上,而是在 Array 原型上。可以通过 Array.prototype 访问这些方法。

6. 空数组和数组的打包

  • 空数组:可以创建一个空数组,用于暂时存储数据或在之后填充数据。

    const emptyArray = [];
    
  • 打包:可以将多个值打包成一个数组,然后通过传递数组来调用函数:

    function sum(nums) {
        return nums.reduce((acc, num) => acc + num, 0);
    }
    console.log(sum([1, 2, 3])); // 输出: 6
    

7. 注意事项

  • 数组的性能:数组在频繁添加和删除元素时,性能可能受到影响,因为需要移动其他元素。
  • 奇异性:虽然数组可以存储不同类型的值,但建议存储相同类型的数据以提高代码的可读性和维护性。

截图数组自带方法就这么多

image.png

方法功能返回注意事项兼容性
 at(index) 返回指定索引位置的元素元素或 undefined 支持负索引从后向前访问ES2022,较新版浏览器
 concat(...args) 合并多个数组并返回新数组新数组不改变原数组广泛支持
 copyWithin(target, start, end) 在数组内部复制元素修改后的数组改变原数组ES2015,IE 不支持
 entries() 返回包含数组每个索引及值的迭代器IteratorES2015
 every(callback) 测试数组中的所有元素是否通过指定的测试函数布尔值处理空数组时返回 true 广泛支持
 fill(value, start, end) 用静态值填充数组,返回修改后的数组修改后的数组改变原数组ES2015,IE 不支持
 filter(callback) 创建新数组,包含所有通过测试的元素新数组处理空数组时返回空数组广泛支持
 find(callback) 返回数组中第一个满足提供测试函数的元素元素或 undefined 处理空数组时返回 undefined ES2015,IE 不支持
 findIndex(callback) 返回数组中第一个满足提供测试函数的元素的索引索引或 -1处理空数组时返回 -1ES2015,IE 不支持
 flat(depth) 返回去嵌套数组的新数组新数组支持深度参数,处理空数组时返回空数组ES2019,IE 不支持
 flatMap(callback) 对每个元素应用函数并返回单一扁平化结果新数组处理空数组时返回空数组ES2019,IE 不支持
 forEach(callback) 遍历数组,对每个元素执行指定的函数 undefined 不返回值广泛支持
 includes(value) 判断数组是否包含某个值布尔值IE 不支持
 indexOf(value) 返回数组中第一个指定值的索引索引或 -1广泛支持
 join(separator) 将数组的所有元素连接成字符串字符串广泛支持
 keys() 返回数组索引的迭代器IteratorES2015
 lastIndexOf(value) 返回数组中指定值最后出现的位置索引或 -1广泛支持
 length 属性,返回数组的元素个数数字广泛支持
 map(callback) 创建新数组,包含对每个元素调用函数的结果新数组处理空数组时返回空数组广泛支持
 pop() 移除数组末尾元素并返回被移除的元素被移除的元素或 undefined 处理空数组时返回 undefined 广泛支持
 push(...items) 向数组末尾添加一个或多个元素并返回新数组长度新数组的长度改变原数组广泛支持
 reduce(callback, initialValue) 通过函数归纳数组元素为单个值单个值初始值为可选广泛支持
 reduceRight(callback, initialValue) 从右到左归纳数组元素为单个值单个值初始值为可选广泛支持
 reverse() 反转数组中的元素顺序反转后的数组改变原数组广泛支持
 shift() 移除数组开头元素并返回被移除的元素被移除的元素或 undefined 处理空数组时返回 undefined 广泛支持
 slice(start, end) 返回数组中指定范围的新数组新数组不改变原数组广泛支持
 some(callback) 测试数组中是否至少有一项满足条件布尔值处理空数组时返回 false 广泛支持
 sort(compareFunction) 对数组进行排序排序后的数组改变原数组广泛支持
 splice(start, deleteCount, ...items) 在数组任意位置添加/删除元素被删除的元素数组改变原数组广泛支持
 toLocaleString() 将数组转换为字符串,使用本地化格式字符串广泛支持
 toString() 将数组转换为字符串字符串广泛支持
 unshift(...items) 在数组开头添加一个或多个元素并返回新数组长度新数组的长度改变原数组广泛支持

在 JavaScript 中,空数组遍历通常不会导致报错,但有些方法在特定情况下可能会出现问题。以下是一些特定的情况,可能导致错误或不可预期的结果:

特别的

1. reduce() 和 reduceRight()

  • 说明:如果对空数组调用 reduce() 或 reduceRight() 且没有提供初始值,会抛出错误。
  • 错误信息TypeError: Reduce of empty array with no initial value
const arr = [];
const result = arr.reduce((acc, curr) => acc + curr); // 报错

2. find() 和 findIndex()

  • 说明:当为空数组时,这些方法不会报错,但返回 undefined 和 -1,可能导致后续逻辑问题。
const arr = [];
const found = arr.find(x => x > 0); // 返回 undefined
const index = arr.findIndex(x => x > 0); // 返回 -1

3. every() 和 some()

  • 说明:对于空数组,这两个方法会返回 true 和 false,这本身不会报错,但需注意后续逻辑。
const arr = [];
const allPositive = arr.every(x => x > 0); // 返回 true
const anyPositive = arr.some(x => x > 0); // 返回 false

4. forEach()

  • 说明:遍历空数组时不会报错,但回调函数不会执行。
const arr = [];
arr.forEach(x => console.log(x)); // 什么都不输出

reduce的齐全用法和高级用法

基础用法

reduce 方法的基本语法是:

array.reduce((accumulator, currentValue, currentIndex, array) => {
    // 返回累加器
}, initialValue);
  • accumulator:累加器,累计回调的返回值;初始值为 initialValue
  • currentValue:当前正在处理的元素。
  • currentIndex (可选):当前元素的索引。
  • array (可选):调用 reduce 的原数组。
  • initialValue (可选):第一次调用回调函数时传给 accumulator 的值。如果没有提供,会使用数组的第一个元素。

示例:基础用法

  1. 数组求和
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 输出: 10
  1. 查找最大值
const numbers = [1, 2, 3, 4];
const max = numbers.reduce((acc, curr) => (curr > acc ? curr : acc), numbers[0]);
console.log(max); // 输出: 4
  1. 扁平化数组
const nestedArray = [[1], [2, 3], [4]];
const flatArray = nestedArray.reduce((acc, curr) => acc.concat(curr), []);
console.log(flatArray); // 输出: [1, 2, 3, 4]

高级用法

  1. 计数对象
const fruits = ['apple', 'banana', 'orange', 'apple', 'banana'];
const fruitCount = fruits.reduce((acc, fruit) => {
    acc[fruit] = (acc[fruit] || 0) + 1;
    return acc;
}, {});
console.log(fruitCount); // 输出: { apple: 2, banana: 2, orange: 1 }
  1. 合并数组对象
const users = [
    { name: 'Tom', age: 25 },
    { name: 'Jerry', age: 30 },
    { name: 'Spike', age: 35 }
];
const ages = users.reduce((acc, user) => {
    acc.push(user.age);
    return acc;
}, []);
console.log(ages); // 输出: [25, 30, 35]
  1. 处理嵌套对象
const data = [
    { id: 1, name: 'Tom', scores: [80, 90, 70] },
    { id: 2, name: 'Jerry', scores: [60, 70] },
];

const totalScores = data.reduce((acc, student) => {
    const total = student.scores.reduce((sum, score) => sum + score, 0);
    acc[student.name] = total;
    return acc;
}, {});

console.log(totalScores); // 输出: { Tom: 240, Jerry: 130 }
  1. 数组去重
const numbers = [1, 2, 3, 1, 2, 4];
const uniqueNumbers = numbers.reduce((acc, curr) => {
    if (!acc.includes(curr)) {
        acc.push(curr);
    }
    return acc;
}, []);
console.log(uniqueNumbers); // 输出: [1, 2, 3, 4]

数组去重 的方法 (不适用数组对象哦适用基本数据类型(如数字和字符串)数组对象的去重有专门的一篇希望你只学一次就毕业)

1. 使用 Set

const numbers = [1, 2, 3, 1, 2, 4];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // 输出: [1, 2, 3, 4]

2. 使用 filter 与 indexOf

const numbers = [1, 2, 3, 1, 2, 4];
const uniqueNumbers = numbers.filter((value, index, self) => self.indexOf(value) === index);
console.log(uniqueNumbers); // 输出: [1, 2, 3, 4]

3. 使用 reduce

const numbers = [1, 2, 3, 1, 2, 4];
const uniqueNumbers = numbers.reduce((acc, curr) => {
  if (!acc.includes(curr)) {
    acc.push(curr);
  }
  return acc;
}, []);
console.log(uniqueNumbers); // 输出: [1, 2, 3, 4]

4. 使用 forEach 与对象记录

const numbers = [1, 2, 3, 1, 2, 4];
const uniqueNumbers = [];
const seen = {};

numbers.forEach(num => {
  if (!seen[num]) {
    uniqueNumbers.push(num);
    seen[num] = true;
  }
});

console.log(uniqueNumbers); // 输出: [1, 2, 3, 4]

5. 使用 Array.from 与 Set

const numbers = [1, 2, 3, 1, 2, 4];
const uniqueNumbers = Array.from(new Set(numbers));
console.log(uniqueNumbers); // 输出: [1, 2, 3, 4]

6. 使用 Map

const numbers = [1, 2, 3, 1, 2, 4];
const uniqueNumbers = [...numbers.reduce((acc, item) => acc.set(item, item), new Map()).values()];
console.log(uniqueNumbers); // 输出: [1, 2, 3, 4]

总结

  • 返回新数组的方法concatslicemapfilterflatflatMapentrieskeysvalues
  • 不返回新数组的方法forEacheverysomereducereduceRightfindfindIndexfillcopyWithinpoppushshiftunshiftsortreversejoinlastIndexOflengthtoLocaleStringtoStringsplice

好了以上就是比较齐全的几乎涵盖了所有js数组的方法对比,基础用法以及注意事项的总结了~一如既往的输出干货,绝对要干无死角的干活;一次学明白学透彻学准确!!!