JavaScript數(shù)組核心方法全面講解(附多場(chǎng)景示例)
一、核心概念
JavaScript 數(shù)組的內(nèi)置方法是開發(fā)中最常用的工具,也是面試高頻考點(diǎn),核心:
- 功能:方法的核心作用
- 返回值:執(zhí)行后返回什么(新數(shù)組 / 單個(gè)值 /undefined)
- 可變性:是否修改原數(shù)組(mutability)
- 使用場(chǎng)景:與其他方法的對(duì)比和選型
| 分類 | 包含方法 | 核心特征 |
|---|---|---|
| 迭代遍歷方法 | forEach、map、filter、reduce、some、every | 遍歷數(shù)組元素并執(zhí)行邏輯 |
| 修改原數(shù)組(Mutator) | push、pop、shift、unshift、splice、sort、reverse | 直接改變?cè)瓟?shù)組,有副作用 |
| 返回新數(shù)組(Non-mutating) | map、filter、concat、slice | 原數(shù)組不變,返回新數(shù)組 |
| 查找判斷方法 | find、findIndex、includes、indexOf | 查找元素或判斷存在性 |
二、為什么要深入理解?
- 代碼簡(jiǎn)潔高效:用高階方法替代冗余的 for 循環(huán),提升代碼可讀性和維護(hù)性;
- 避免副作用:明確可變性,防止在 React/Vue/Redux 等狀態(tài)管理中誤改原數(shù)據(jù);
- 面試核心考點(diǎn):手動(dòng)實(shí)現(xiàn) map/reduce、區(qū)分 slice/splice、判斷方法可變性是高頻面試題;
- 性能優(yōu)化:不同方法的執(zhí)行效率不同(如 reduce 比嵌套循環(huán)更高效)。
三、核心方法詳解(附多場(chǎng)景示例)
1. 迭代遍歷方法
(1) map () - 數(shù)組轉(zhuǎn)換(返回新數(shù)組)工作中最常使用
- 核心:遍歷數(shù)組,對(duì)每個(gè)元素執(zhí)行回調(diào),返回新數(shù)組(長(zhǎng)度與原數(shù)組一致)
- 可變性:不修改原數(shù)組
- 返回值:新數(shù)組
- 適用場(chǎng)景:數(shù)據(jù)格式轉(zhuǎn)換、批量處理元素
基礎(chǔ)示例:
const numbers = [1, 4, 9]; const doubles = numbers.map(num => num * 2); console.log(doubles); // [2, 8, 18] console.log(numbers); // [1, 4, 9](原數(shù)組不變)
實(shí)戰(zhàn)示例:對(duì)象數(shù)組屬性提取
const users = [
{ id: 1, name: '張三', age: 20 },
{ id: 2, name: '李四', age: 25 },
{ id: 3, name: '王五', age: 30 }
];
// 提取所有用戶名
const userNames = users.map(user => user.name);
console.log(userNames); // ["張三", "李四", "王五"]
// 批量修改屬性(返回新對(duì)象)
const adultUsers = users.map(user => ({
...user,
isAdult: user.age >= 18 // 新增屬性
}));
console.log(adultUsers[0]); // { id: 1, name: '張三', age: 20, isAdult: true }(2) filter () - 數(shù)組過濾(返回新數(shù)組)
- 核心:遍歷數(shù)組,篩選出符合條件的元素,返回新數(shù)組
- 可變性:不修改原數(shù)組
- 返回值:新數(shù)組(長(zhǎng)度≤原數(shù)組)
- 適用場(chǎng)景:數(shù)據(jù)篩選、條件過濾
基礎(chǔ)示例:
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction']; const longWords = words.filter(word => word.length > 6); console.log(longWords); // ["exuberant", "destruction"] [].filter(Boolean) //可以過濾掉null
實(shí)戰(zhàn)示例:多條件過濾
const products = [
{ name: '手機(jī)', price: 2999, category: '數(shù)碼', stock: 50 },
{ name: '耳機(jī)', price: 199, category: '數(shù)碼', stock: 0 },
{ name: 'T恤', price: 99, category: '服飾', stock: 100 },
{ name: '鍵盤', price: 499, category: '數(shù)碼', stock: 30 }
];
// 篩選:數(shù)碼類、價(jià)格<500、有庫存的商品
const validProducts = products.filter(p =>
p.category === '數(shù)碼' && p.price < 500 && p.stock > 0
);
console.log(validProducts); // [{ name: '耳機(jī)', ... }, { name: '鍵盤', ... }](3) reduce () - 數(shù)組歸并(返回單個(gè)值)
- 核心:遍歷數(shù)組,將元素 “累積” 為單個(gè)值(數(shù)字、對(duì)象、數(shù)組等)
- API:
arr.reduce((acc, cur, idx, arr) => {}, initialValue)acc:累加器(上一次回調(diào)的返回值 / 初始值)cur:當(dāng)前元素initialValue:可選,累加器初始值(推薦必傳)
- 可變性:不修改原數(shù)組
- 適用場(chǎng)景:求和 / 求積、數(shù)組轉(zhuǎn)對(duì)象、扁平數(shù)組、分組統(tǒng)計(jì)
基礎(chǔ)示例:求和
const array = [1, 2, 3, 4]; const sum = array.reduce((acc, cur) => acc + cur, 0); console.log(sum); // 10
實(shí)戰(zhàn)示例 1:數(shù)組轉(zhuǎn)對(duì)象(按 ID 映射)
const users = [
{ id: 1, name: '張三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' }
];
// 轉(zhuǎn)換為 { 1: { id:1, name:'張三' }, 2: { ... } }
const userMap = users.reduce((acc, cur) => {
acc[cur.id] = cur;
return acc;
}, {});
console.log(userMap[2]); // { id: 2, name: '李四' }實(shí)戰(zhàn)示例 2:扁平嵌套數(shù)組
const nestedArr = [1, [2, [3, 4], 5], 6];
const flatArr = nestedArr.reduce((acc, cur) => {
return acc.concat(Array.isArray(cur) ? cur.reduce((a, c) => a.concat(c), []) : cur);
}, []);
console.log(flatArr); // [1, 2, 3, 4, 5, 6]實(shí)戰(zhàn)示例 3:分組統(tǒng)計(jì)
const scores = [
{ name: '張三', subject: '數(shù)學(xué)', score: 90 },
{ name: '張三', subject: '語文', score: 85 },
{ name: '李四', subject: '數(shù)學(xué)', score: 88 },
{ name: '李四', subject: '語文', score: 92 }
];
// 按姓名分組,統(tǒng)計(jì)總分
const scoreSum = scores.reduce((acc, cur) => {
if (!acc[cur.name]) {
acc[cur.name] = 0;
}
acc[cur.name] += cur.score;
return acc;
}, {});
console.log(scoreSum); // { 張三: 175, 李四: 180 }(4) forEach () - 遍歷執(zhí)行(無返回值)
- 核心:遍歷數(shù)組,對(duì)每個(gè)元素執(zhí)行回調(diào)(僅執(zhí)行操作,無返回值)
- 可變性:本身不修改原數(shù)組,但回調(diào)中可手動(dòng)修改
- 返回值:undefined
- 適用場(chǎng)景:執(zhí)行副作用操作(如打印、調(diào)用 API、修改 DOM)
示例:
const fruits = ['蘋果', '香蕉', '橙子'];
// 打印每個(gè)元素
fruits.forEach((fruit, index) => {
console.log(`第${index+1}個(gè)水果:${fruit}`);
});
// 第1個(gè)水果:蘋果 | 第2個(gè)水果:香蕉 | 第3個(gè)水果:橙子
// 注意:forEach 無法中斷遍歷(break 無效),需用 some/every 替代(5) some ()/every () - 條件判斷
- some:只要有一個(gè)元素滿足條件,返回 true(短路遍歷)
- every:所有元素滿足條件,返回 true(短路遍歷)
- 返回值:布爾值
- 適用場(chǎng)景:判斷數(shù)組是否符合某個(gè)條件
示例:
const numbers = [10, 20, 30, 35];
// some:是否有元素>30
const hasBigNum = numbers.some(num => num > 30);
console.log(hasBigNum); // true
// every:是否所有元素>15
const allBigNum = numbers.every(num => num > 15);
console.log(allBigNum); // false(10不滿足)
// 實(shí)戰(zhàn):判斷是否有已過期的訂單
const orders = [
{ id: 1, expired: false },
{ id: 2, expired: true },
{ id: 3, expired: false }
];
const hasExpired = orders.some(order => order.expired);
console.log(hasExpired); // true2. 修改原數(shù)組的方法(Mutator)
(1) splice () - 增刪改數(shù)組(核心)
- 核心:刪除 / 插入 / 替換數(shù)組元素(原地修改)
- API:
arr.splice(start, deleteCount, item1, item2...)start:起始索引(負(fù)數(shù)表示從末尾開始)deleteCount:刪除的元素?cái)?shù)量(0 則不刪除)item...:要插入的元素
- 返回值:被刪除的元素組成的數(shù)組
- 可變性:修改原數(shù)組
示例 1:插入元素
const months = ['Jan', 'March', 'April', 'June']; // 索引1的位置,刪除0個(gè),插入'Feb' const removed = months.splice(1, 0, 'Feb'); console.log(months); // ["Jan", "Feb", "March", "April", "June"] console.log(removed); // [](無刪除)
示例 2:刪除元素
const arr = [1, 2, 3, 4, 5]; // 索引2的位置,刪除2個(gè)元素 const deleted = arr.splice(2, 2); console.log(arr); // [1, 2, 5] console.log(deleted); // [3, 4]
示例 3:替換元素
const arr = ['a', 'b', 'c', 'd']; // 索引1的位置,刪除1個(gè),插入'x'和'y' arr.splice(1, 1, 'x', 'y'); console.log(arr); // ["a", "x", "y", "c", "d"]
(2) push/pop/shift/unshift - 數(shù)組首尾操作
| 方法 | 功能 | 返回值 | 示例 |
|---|---|---|---|
| push | 尾部添加元素 | 新數(shù)組長(zhǎng)度 | const arr = [1,2]; arr.push(3); // arr=[1,2,3],返回3 |
| pop | 尾部刪除元素 | 被刪除的元素 | const arr = [1,2,3]; arr.pop(); // arr=[1,2],返回3 |
| unshift | 頭部添加元素 | 新數(shù)組長(zhǎng)度 | const arr = [2,3]; arr.unshift(1); // arr=[1,2,3],返回3 |
| shift | 頭部刪除元素 | 被刪除的元素 | const arr = [1,2,3]; arr.shift(); // arr=[2,3],返回1 |
(3) sort/reverse - 排序 / 反轉(zhuǎn)
- sort:原地排序,默認(rèn)按字符串 Unicode 碼排序(需傳回調(diào)自定義規(guī)則)
- reverse:原地反轉(zhuǎn)數(shù)組順序
示例:
// sort 自定義排序(數(shù)字升序) const numbers = [10, 2, 25, 5]; numbers.sort((a, b) => a - b); console.log(numbers); // [2, 5, 10, 25] // reverse 反轉(zhuǎn) const arr = [1, 2, 3]; arr.reverse(); console.log(arr); // [3, 2, 1]
3. 返回新數(shù)組的方法(Non-mutating)
(1) slice () - 截取數(shù)組片段
- 核心:截取數(shù)組的指定范圍,返回新數(shù)組(淺拷貝)
- API:
arr.slice(start, end)(start 包含,end 不包含,負(fù)數(shù)表示末尾) - 可變性:不修改原數(shù)組
- 返回值:新數(shù)組
示例:
const arr = [1, 2, 3, 4, 5]; // 截取索引1到3(不包含3) const slice1 = arr.slice(1, 3); console.log(slice1); // [2, 3] // 截取最后2個(gè)元素 const slice2 = arr.slice(-2); console.log(slice2); // [4, 5] // 淺拷貝整個(gè)數(shù)組 const copyArr = arr.slice(); copyArr[0] = 10; console.log(arr); // [1, 2, 3, 4, 5](原數(shù)組不變)
(2) concat () - 數(shù)組合并
- 核心:合并多個(gè)數(shù)組 / 值,返回新數(shù)組
- 可變性:不修改原數(shù)組
- 返回值:新數(shù)組
示例:
const arr1 = [1, 2]; const arr2 = [3, 4]; const arr3 = arr1.concat(arr2, 5); console.log(arr3); // [1, 2, 3, 4, 5] console.log(arr1); // [1, 2](原數(shù)組不變)
4. 易混淆方法對(duì)比
(1) map vs forEach
| 維度 | map | forEach |
|---|---|---|
| 返回值 | 新數(shù)組 | undefined |
| 用途 | 數(shù)據(jù)轉(zhuǎn)換,需返回新數(shù)組 | 執(zhí)行操作(打印、調(diào) API),無需返回值 |
| 鏈?zhǔn)秸{(diào)用 | 支持(map ().filter ()) | 不支持(返回 undefined) |
(2) slice vs splice
| 維度 | slice | splice |
|---|---|---|
| 可變性 | 不修改原數(shù)組 | 修改原數(shù)組 |
| 功能 | 截取數(shù)組片段 | 增刪改數(shù)組元素 |
| 參數(shù) | slice(start, end) | splice(start, deleteCount, ...items) |
| 返回值 | 截取的新數(shù)組 | 被刪除的元素?cái)?shù)組 |
(3) reduce 有無 initialValue 的區(qū)別
| 場(chǎng)景 | 有 initialValue | 無 initialValue |
|---|---|---|
| 空數(shù)組 | 返回 initialValue | 拋出 TypeError |
| 非空數(shù)組 | acc 初始值 = initialValue,從第一個(gè)元素開始遍歷 | acc 初始值 = 第一個(gè)元素,從第二個(gè)元素開始遍歷 |
示例:
// 有 initialValue(推薦) [1,2,3].reduce((acc, cur) => acc + cur, 0); // 6(acc初始=0,遍歷1→2→3) // 無 initialValue [1,2,3].reduce((acc, cur) => acc + cur); // 6(acc初始=1,遍歷2→3) // 空數(shù)組 + 無 initialValue → 報(bào)錯(cuò) // [].reduce((acc, cur) => acc + cur); // Uncaught TypeError
四、關(guān)鍵注意事項(xiàng)
- 可變性避坑:
- React/Vue 中,禁止直接修改 state 數(shù)組(如
state.arr.push(1)),需用非變異方法([...state.arr, 1]); - 如需修改原數(shù)組,先淺拷貝(
const copy = [...arr])再操作。
- React/Vue 中,禁止直接修改 state 數(shù)組(如
- 稀疏數(shù)組處理:
- map/forEach/filter 會(huì)跳過稀疏數(shù)組的空位(
[1,,3].map(x => x*2)→[2,,6]); - reduce 也會(huì)跳過空位(除非傳 initialValue)。
- map/forEach/filter 會(huì)跳過稀疏數(shù)組的空位(
- 性能優(yōu)化:
- 避免嵌套迭代(如 map 里套 filter),優(yōu)先用 reduce 一次遍歷;
- 大數(shù)據(jù)量遍歷,for 循環(huán)比 forEach/map 更快(高階方法有函數(shù)調(diào)用開銷)。
手動(dòng)實(shí)現(xiàn)核心方法(面試必考)
// 手動(dòng)實(shí)現(xiàn) map
Array.prototype.myMap = function(callback) {
const newArr = [];
for (let i = 0; i < this.length; i++) {
if (i in this) { // 處理稀疏數(shù)組
newArr[i] = callback(this[i], i, this);
}
}
return newArr;
};
// 手動(dòng)實(shí)現(xiàn) reduce
Array.prototype.myReduce = function(callback, initialValue) {
let acc = initialValue;
let startIndex = 0;
// 無 initialValue 時(shí),acc 初始化為第一個(gè)元素
if (initialValue === undefined) {
if (this.length === 0) throw new TypeError('空數(shù)組無初始值');
acc = this[0];
startIndex = 1;
}
for (let i = startIndex; i < this.length; i++) {
if (i in this) {
acc = callback(acc, this[i], i, this);
}
}
return acc;
};總結(jié)
到此這篇關(guān)于JavaScript數(shù)組核心方法(附多場(chǎng)景示例)的文章就介紹到這了,更多相關(guān)JS數(shù)組核心方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于JavaScript制作一個(gè)簡(jiǎn)單的天氣應(yīng)用
隨著Web開發(fā)技術(shù)的不斷發(fā)展,JavaScript已經(jīng)成為前端開發(fā)中不可或缺的一部分,下面我們就來看看如何使用JavaScript實(shí)現(xiàn)一個(gè)簡(jiǎn)單的天氣應(yīng)用吧2024-01-01
javascript進(jìn)行數(shù)組追加方法小結(jié)
javascript中給數(shù)組加元素是一個(gè)非常簡(jiǎn)單的問題,javascript本身就提供了大量這類函數(shù),我們可以使用js自帶函數(shù)快速給數(shù)組增加元素了,本文就javascript進(jìn)行數(shù)組追加的方法做出如下小結(jié)。2014-06-06
JavaScript 操作table,可以新增行和列并且隔一行換背景色代碼分享
這篇文章介紹了JavaScript操作table,可以新增行和列并且隔一行換背景色代碼,有需要的朋友可以參考一下2013-07-07
一文詳解JavaScript中==和===的區(qū)別與正確使用場(chǎng)景
在 JavaScript 面試中,== 和 === 有什么區(qū)別,分別在什么情況使用,本文將從定義,規(guī)則、,差異對(duì)比到實(shí)戰(zhàn)場(chǎng)景,全面解析二者的核心邏輯2025-09-09

