JavaScript数组

JavaScript / ECMAScript Array 的定位、创建方式、常用方法与高频边界。

#type / concept #status / growing #resource / javascript #resource / ecmascript

[!info] related notes

JavaScript数组

Array 是 ECMAScript 里最常用的集合类型之一。它本质上是特殊对象,但在使用上更应该把它理解为”有顺序、可变长、带大量内置方法的数据容器”。

最短理解

  • 有顺序,可以通过索引访问
  • 动态长度,可以随时增删元素
  • 同一个数组里可以混合多种值类型
  • 它是对象,但语义更偏”列表容器”
const arr = [1, 'hello', { name: 'Alice' }, [2, 3]];

创建方式

  • 数组字面量: []
  • Array.of(...)
  • Array.from(...)
  • new Array(...)

默认更推荐字面量;new Array(5) 这种单个数字参数写法容易让人误读成”有一个元素的数组”,实际上它创建的是长度为 5 的稀疏数组。

空位与稀疏数组

const options = [,,,,,];

这表示存在 5 个空位,不等于 5 个显式的 undefined。很多数组方法在处理空位时的行为并不完全一致,所以除非确实需要,通常不建议主动制造稀疏数组。

如何判断一个值是不是数组

优先使用 Array.isArray()

instanceof Array 在跨 iframe / 跨 realm 场景里可能失准,而 Array.isArray() 更稳定。


完整方法速查表

增删改(修改原数组)

方法作用返回值备注
.push(...items)末尾添加新长度
.pop()末尾删除被删元素
.unshift(...items)开头添加新长度
.shift()开头删除被删元素
.splice(start, deleteCount, ...items)任意位置增删改被删元素数组会改原数组
.copyWithin(target, start, end?)内部复制修改后的数组ES6
.fill(value, start?, end?)填充修改后的数组ES6

复制与变换(不改原数组)

方法作用返回值
.slice(start?, end?)浅拷贝片段新数组
.concat(...items)合并数组新数组
.flat(depth?)扁平化新数组(ES2019)
.flatMap(callback)map + flat(1)新数组(ES2019)
.map(callback)映射每个元素新数组
.filter(callback)过滤新数组
.reduce(callback, init?)累积最终值
.reduceRight(callback, init?)从右累积最终值

查找与判断

方法作用返回值
.indexOf(item, from?)查找索引索引或 -1
.lastIndexOf(item, from?)从右查找索引索引或 -1
.includes(item, from?)是否包含boolean
.find(callback)查找第一个匹配元素元素或 undefined
.findIndex(callback)查找第一个匹配索引索引或 -1
.findLast(callback)从右查找第一个匹配元素(ES2023)
.findLastIndex(callback)从右查找第一个匹配索引索引(ES2023)
.some(callback)是否有满足条件的boolean
.every(callback)是否全部满足条件boolean

排序与反转

方法作用返回值备注
.sort(compareFn?)排序修改后的数组会改原数组
.reverse()反转修改后的数组会改原数组
.toSorted(compareFn?)排序(不改原数组)新数组(ES2023)
.toReversed()反转(不改原数组)新数组(ES2023)

遍历

方法作用返回值
.forEach(callback)遍历undefined
.map(callback)映射新数组
.filter(callback)过滤新数组
.reduce(callback, init?)累积最终值
.some(callback)部分满足?boolean
.every(callback)全部满足?boolean
.keys()键迭代器Iterator
.values()值迭代器Iterator
.entries()键值对迭代器Iterator

转换与拼接

方法作用返回值
.join(separator?)转字符串string
.toString()转字符串(逗号分隔)string
.toLocaleString()本地化字符串string
.concat(...items)拼接数组新数组
...spread展开运算符(语法)

静态方法

方法作用
Array.isArray(v)判断是否数组
Array.from(iterable, mapFn?)从可迭代对象创建数组
Array.of(...items)从参数创建数组
Array.fromAsync(iterable, mapFn?)异步版本(ES2024)

最容易踩坑的点

sort 默认按字符串比较

[10, 9, 80, 1].sort();          // [1, 10, 80, 9](按字符串排序)
[10, 9, 80, 1].sort((a, b) => a - b); // [1, 9, 10, 80](数值排序)

slice vs splice

// slice 不改原数组,返回新数组
const arr = [1, 2, 3, 4, 5];
arr.slice(1, 3);    // [2, 3]
arr;                 // [1, 2, 3, 4, 5]

// splice 改原数组,返回被删除的元素
arr.splice(1, 2);    // [2, 3]
arr;                 // [1, 4, 5]

map vs forEach

// map 返回新数组
const doubled = [1, 2, 3].map(x => x * 2); // [2, 4, 6]

// forEach 返回 undefined,用于副作用
[1, 2, 3].forEach(x => console.log(x)); // undefined

稀疏数组 vs undefined

const sparse = [1, , 3];      // 稀疏,长度 3,有空位
const explicit = [1, undefined, 3]; // 明确有 undefined

sparse.map(x => x * 2);       // [2, empty, 6](跳过空位)
explicit.map(x => x * 2);    // [2, NaN, 6]

常用模式

数组去重

const unique = [...new Set(arr)];
const unique2 = arr.filter((v, i) => arr.indexOf(v) === i);

数组扁平化

const nested = [1, [2, [3, [4]]]];
nested.flat();      // [1, 2, [3, [4]]]
nested.flat(2);     // [1, 2, 3, [4]]
nested.flat(Infinity); // [1, 2, 3, 4]

分组统计

// 按某个属性分组
const grouped = arr.reduce((acc, item) => {
  const key = item.category;
  acc[key] = acc[key] || [];
  acc[key].push(item);
  return acc;
}, {});

// ES2024: Object.groupBy
const grouped2 = Object.groupBy(arr, item => item.category);

数组转 Map

const map = new Map(arr.map(item => [item.id, item]));

排序去重

const sorted = [...new Set(arr)].sort((a, b) => a - b);

分块

function chunk(arr, size) {
  const result = [];
  for (let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }
  return result;
}
chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]

一个常见 reduce() 例子

const arr = [1, 2, [3, 4], [5, 6]];

function flatArray(arr) {
  return arr.reduce((result, item) => {
    if (Array.isArray(item)) {
      return [...result, ...flatArray(item)];
    }

    return [...result, item];
  }, []);
}

这个例子适合用来建立 reduce() 的直觉:它不是”数组专属魔法”,而是把一组元素持续累加到一个结果值里的通用接口。


ES2023 新增方法(不改原数组)

方法作用对应的原方法
.toSorted()排序.sort()
.toReversed()反转.reverse()
.toSpliced()splice.splice()
.with(index, value)替换指定位置arr[index] = value
.findLast()从右查找.find()
.findLastIndex()从右查找索引.findIndex()

延伸阅读

创建于 2025/1/1 更新于 2026/5/27