JavaScript 數(shù)組從基礎到高級核心操作方法
概述
JavaScript 數(shù)組是開發(fā)中最常用的數(shù)據(jù)結構之一,掌握其操作方法對于提高編程效率至關重要。以下是我整理的完整數(shù)組操作指南。
一、數(shù)組創(chuàng)建與初始化
在 JavaScript 中,有多種方式可以創(chuàng)建和初始化數(shù)組。不同的方法適用于不同的場景,理解它們的區(qū)別有助于寫出更清晰、更安全的代碼。
// 1. 字面量創(chuàng)建
const arr1 = [1, 2, 3, 4, 5];
const arr2 = ['a', 'b', 'c'];
// 2. 構造函數(shù)創(chuàng)建
const arr3 = new Array(5); // 創(chuàng)建長度為5的空數(shù)組
const arr4 = new Array(1, 2, 3); // 創(chuàng)建包含元素的數(shù)組
// 3. Array.of() - 解決構造函數(shù)歧義
Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]
// 4. Array.from() - 從類數(shù)組或可迭代對象創(chuàng)建
Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
Array.from({ length: 5 }); // [undefined, undefined, ...]
Array.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4]
// 5. 填充數(shù)組
const filled1 = new Array(5).fill(0); // [0, 0, 0, 0, 0]
const filled2 = Array.from({ length: 5 }, () => 1); // [1, 1, 1, 1, 1]說明:
- 使用字面量
[]是最常見且推薦的方式,簡潔直觀。new Array(n)當傳入單個數(shù)字時會創(chuàng)建稀疏數(shù)組(holes),行為容易出錯,應避免。Array.of()能安全地創(chuàng)建指定元素的數(shù)組,解決了new Array()的歧義問題。Array.from()不僅能將類數(shù)組(如 arguments、NodeList)轉為真實數(shù)組,還能結合length和映射函數(shù)生成序列或初始化數(shù)組。fill()和Array.from()配合使用,是初始化固定值數(shù)組的常用手段。
二、元素增刪操作
數(shù)組的增刪操作分為在頭部、尾部或任意位置進行。不同方法對性能和原數(shù)組的影響不同,需根據(jù)場景選擇合適的方法。
1. 尾部操作
尾部操作是最高效的數(shù)組修改方式,因為不會影響其他元素的索引。
const arr = [1, 2, 3]; // push - 尾部添加元素 arr.push(4); // 返回新長度: 4, arr: [1, 2, 3, 4] arr.push(5, 6); // 可添加多個: [1, 2, 3, 4, 5, 6] // pop - 尾部刪除元素 const last = arr.pop(); // last = 6, arr: [1, 2, 3, 4, 5]
說明:
push()可接收多個參數(shù),一次性添加多個元素,返回新長度。pop()刪除并返回最后一個元素,數(shù)組為空時返回undefined。- 這兩個方法直接修改原數(shù)組,適用于需要累積數(shù)據(jù)的場景(如棧結構)。
2. 頭部操作
頭部操作效率較低,因為每次添加或刪除都會導致所有后續(xù)元素索引前移或后移。
// unshift - 頭部添加元素 arr.unshift(0); // 返回新長度: 6, arr: [0, 1, 2, 3, 4, 5] arr.unshift(-2, -1); // [-2, -1, 0, 1, 2, 3, 4, 5] // shift - 頭部刪除元素 const first = arr.shift(); // first = -2, arr: [-1, 0, 1, 2, 3, 4, 5]
說明:
unshift()在數(shù)組開頭插入一個或多個元素,返回新長度。shift()刪除并返回第一個元素,數(shù)組為空返回undefined。- 由于性能開銷較大,應避免在大型數(shù)組中頻繁使用。
3. 任意位置操作
splice() 是最靈活的數(shù)組修改方法,可以在任意位置添加、刪除或替換元素。
const arr = [1, 2, 3, 4, 5]; // splice - 多功能修改 // 刪除:從索引2開始刪除1個元素 arr.splice(2, 1); // 返回刪除元素: [3], arr: [1, 2, 4, 5] // 添加:從索引1開始刪除0個元素,添加新元素 arr.splice(1, 0, 'a', 'b'); // arr: [1, 'a', 'b', 2, 4, 5] // 替換:從索引3開始刪除2個元素,添加新元素 arr.splice(3, 2, 'c', 'd'); // 返回刪除元素: [2, 4], arr: [1, 'a', 'b', 'c', 'd']
說明:
splice(start, deleteCount, item1, item2, ...)從start開始刪除deleteCount個元素,并插入新元素。- 返回被刪除的元素組成的數(shù)組。
- 該方法直接修改原數(shù)組,適合精確控制數(shù)組結構的場景。
4. 清空數(shù)組
清空數(shù)組有多種方式,但行為和性能略有差異。
let arr = [1, 2, 3]; // 方法1: 重新賦值 (推薦) arr = []; // 方法2: 修改length屬性 arr.length = 0; // 方法3: splice arr.splice(0, arr.length);
說明:
- 重新賦值
arr = []最簡潔,但如果其他變量引用原數(shù)組,則原數(shù)組仍存在。arr.length = 0會清空所有引用該數(shù)組的變量,是徹底清空的可靠方式。splice(0)同樣能清空并保留引用,但語法稍顯復雜。- 推薦使用
length = 0或重新賦值,視引用情況而定。
三、數(shù)組遍歷方法
遍歷數(shù)組是日常開發(fā)中最常見的操作。不同遍歷方式在語法、性能和用途上各有優(yōu)劣。
const numbers = [1, 2, 3, 4, 5];
// 1. for循環(huán) (最基礎)
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
// 2. for...of循環(huán) (推薦)
for (const num of numbers) {
console.log(num);
}
// 3. forEach方法
numbers.forEach((num, index, array) => {
console.log(`索引 ${index}: 值 ${num}`);
});
// 4. for...in (不推薦用于數(shù)組,會遍歷所有可枚舉屬性)
for (const index in numbers) {
console.log(numbers[index]);
}
// 5. entries() 獲取索引和值
for (const [index, value] of numbers.entries()) {
console.log(index, value);
}說明:
for循環(huán)性能最好,支持break、continue,適合復雜邏輯。for...of語法簡潔,支持break和yield,推薦用于簡單遍歷。forEach()語義清晰,但無法中途跳出(return僅結束當前回調)。for...in用于對象,不推薦用于數(shù)組,可能遍歷到非數(shù)字索引或原型屬性。entries()結合for...of可同時獲取索引和值,是現(xiàn)代 JS 的優(yōu)雅寫法。
四、查找與篩選
查找和篩選是處理數(shù)組數(shù)據(jù)的核心能力,尤其在處理用戶列表、表單驗證等場景中非常關鍵。
1. 查找元素
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 25 }
];
// find - 查找第一個符合條件的元素
const user = users.find(u => u.age === 25); // { id: 1, name: 'Alice', age: 25 }
// findIndex - 查找第一個符合條件的元素索引
const index = users.findIndex(u => u.name === 'Bob'); // 1
// findLast / findLastIndex (ES2023)
const last25 = users.findLast(u => u.age === 25); // { id: 3, name: 'Charlie', age: 25 }
// includes - 檢查是否包含某元素
[1, 2, 3].includes(2); // true
// indexOf / lastIndexOf - 查找元素位置
['a', 'b', 'c', 'b'].indexOf('b'); // 1
['a', 'b', 'c', 'b'].lastIndexOf('b'); // 3說明:
find()返回第一個匹配元素,未找到返回undefined。findIndex()返回索引,未找到返回-1,適合需要索引的場景。findLast和findLastIndex是 ES2023 新增,從末尾開始查找。includes()用于基本類型比較,使用===判斷。indexOf()對于對象數(shù)組不適用(引用不同),應配合find使用。
2. 篩選數(shù)組
const numbers = [1, 2, 3, 4, 5, 6];
// filter - 篩選符合條件的元素
const even = numbers.filter(n => n % 2 === 0); // [2, 4, 6]
const adults = users.filter(u => u.age >= 18);
// 鏈式調用
const result = users
.filter(u => u.age > 20)
.map(u => u.name); // ['Bob', 'Charlie']說明:
filter()返回一個新數(shù)組,包含所有滿足條件的元素,不修改原數(shù)組。- 與
find()不同,filter()返回數(shù)組,即使只有一個匹配項。- 支持鏈式調用,常與
map()、sort()等組合使用,實現(xiàn)函數(shù)式編程風格。
五、數(shù)組轉換
數(shù)組轉換是函數(shù)式編程的核心,通過映射、扁平化和歸約,可以將數(shù)據(jù)結構靈活變換。
1. 映射轉換
const numbers = [1, 2, 3];
// map - 將數(shù)組映射為新數(shù)組
const doubled = numbers.map(n => n * 2); // [2, 4, 6]
const userNames = users.map(u => u.name); // ['Alice', 'Bob', 'Charlie']
// flatMap - 映射后扁平化 (ES2019)
const phrases = ['hello world', 'good morning'];
const words = phrases.flatMap(phrase => phrase.split(' '));
// ['hello', 'world', 'good', 'morning']說明:
map()是最常用的轉換方法,將每個元素通過函數(shù)映射為新值。- 返回新數(shù)組,長度與原數(shù)組相同。
flatMap()先map再flat(1),適合將一個元素映射為多個并展平,避免嵌套。
2. 扁平化數(shù)組
const nested = [1, [2, [3, [4]]]];
// flat - 扁平化數(shù)組 (ES2019)
nested.flat(); // [1, 2, [3, [4]]]
nested.flat(2); // [1, 2, 3, [4]]
nested.flat(Infinity); // [1, 2, 3, 4]
// 替代方案 (ES6)
const flatten = arr => arr.reduce((acc, val) =>
acc.concat(Array.isArray(val) ? flatten(val) : val), []);說明:
flat(depth)將嵌套數(shù)組按指定深度展平。Infinity可完全展平任意深度嵌套。- 舊版可用
reduce + concat + 遞歸實現(xiàn),但性能較差。
3. 歸約操作
const numbers = [1, 2, 3, 4, 5];
// reduce - 從左到右歸約
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 15
const max = numbers.reduce((acc, curr) => Math.max(acc, curr), -Infinity); // 5
// reduceRight - 從右到左歸約
const reversed = numbers.reduceRight((acc, curr) => [...acc, curr], []); // [5, 4, 3, 2, 1]
// 復雜示例:統(tǒng)計字符出現(xiàn)次數(shù)
const chars = ['a', 'b', 'a', 'c', 'b', 'a'];
const count = chars.reduce((acc, char) => {
acc[char] = (acc[char] || 0) + 1;
return acc;
}, {}); // { a: 3, b: 2, c: 1 }說明:
reduce()是函數(shù)式編程的“瑞士軍刀”,可用于求和、拼接、分組、狀態(tài)累積等。- 接收累加器
acc和當前值curr,初始值通過第二個參數(shù)指定。reduceRight()從右向左處理,適用于需要逆序操作的場景。
六、排序與反轉
排序和反轉是改變數(shù)組順序的常用操作,但需注意它們會修改原數(shù)組。
const numbers = [3, 1, 4, 1, 5, 9]; const names = ['John', 'Alice', 'Bob']; // sort - 排序 (會修改原數(shù)組) numbers.sort(); // [1, 1, 3, 4, 5, 9] - 默認按字符串排序 numbers.sort((a, b) => a - b); // 數(shù)字升序 numbers.sort((a, b) => b - a); // 數(shù)字降序 names.sort(); // ['Alice', 'Bob', 'John'] - 字符串排序 // 對象數(shù)組排序 users.sort((a, b) => a.age - b.age); // 按年齡升序 users.sort((a, b) => a.name.localeCompare(b.name)); // 按姓名排序 // reverse - 反轉數(shù)組 numbers.reverse(); // [9, 5, 4, 3, 1, 1] // 創(chuàng)建排序副本 (不修改原數(shù)組) const sorted = [...numbers].sort(); const sorted2 = numbers.slice().sort(); // 等效
說明:
sort()默認將元素轉為字符串比較,數(shù)字排序必須提供比較函數(shù)(a, b) => a - b。localeCompare()用于安全的字符串排序,支持多語言。reverse()直接反轉原數(shù)組。- 如需保留原數(shù)組,應使用擴展運算符或
slice()創(chuàng)建副本后再排序。
七、數(shù)組切片與連接
切片和連接用于提取子數(shù)組或合并多個數(shù)組,是構建新數(shù)組的重要手段。
const arr = [1, 2, 3, 4, 5];
// slice - 切片 (不修改原數(shù)組)
arr.slice(1, 3); // [2, 3] - 索引1到3(不含)
arr.slice(2); // [3, 4, 5] - 從索引2到最后
arr.slice(-2); // [4, 5] - 最后兩個元素
arr.slice(1, -1); // [2, 3, 4] - 從1到倒數(shù)第1個
// concat - 連接數(shù)組
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = arr1.concat(arr2); // [1, 2, 3, 4]
const combined2 = [...arr1, ...arr2]; // ES6擴展運算符 (推薦)
// join - 數(shù)組轉字符串
['Hello', 'World'].join(' '); // "Hello World"
[1, 2, 3].join('-'); // "1-2-3"說明:
slice(start, end)提取從start到end(不含)的子數(shù)組,支持負索引。concat()可連接多個數(shù)組或值,返回新數(shù)組。- 擴展運算符
...語法更簡潔,是現(xiàn)代 JS 的首選方式。join(separator)將數(shù)組元素拼接為字符串,常用于生成路徑、標簽等。
八、高階函數(shù)應用
高階函數(shù)讓數(shù)組操作更具表達力,支持函數(shù)式編程范式,提升代碼可維護性。
1. 條件判斷
const numbers = [1, 2, 3, 4, 5];
// every - 所有元素都滿足條件
numbers.every(n => n > 0); // true
// some - 至少一個元素滿足條件
numbers.some(n => n > 4); // true
// 實用示例
const formFields = [{ value: 'abc' }, { value: '' }, { value: 'def' }];
const allFilled = formFields.every(field => field.value.trim() !== ''); // false
const anyFilled = formFields.some(field => field.value.trim() !== ''); // true說明:
every()類似邏輯與(AND),全部為真才返回true。some()類似邏輯或(OR),任一為真即返回true。- 常用于表單驗證、權限檢查、狀態(tài)判斷等場景。
2. 函數(shù)式編程模式
// 管道操作模擬
const pipe = (...fns) => (initialValue) =>
fns.reduce((acc, fn) => fn(acc), initialValue);
// 組合函數(shù)
const processNumbers = pipe(
arr => arr.filter(n => n % 2 === 0), // 篩選偶數(shù)
arr => arr.map(n => n * 2), // 乘以2
arr => arr.reduce((a, b) => a + b, 0) // 求和
);
processNumbers([1, 2, 3, 4, 5]); // 12 (2*2 + 4*2 = 4 + 8)說明:
- 函數(shù)式編程強調無副作用、數(shù)據(jù)不可變和函數(shù)組合。
pipe()實現(xiàn)了函數(shù)的鏈式調用,每個函數(shù)接收上一個的輸出。- 適合處理數(shù)據(jù)流、構建 DSL 或復雜轉換邏輯。
九、ES6+ 新特性
ES6 及后續(xù)版本為數(shù)組操作帶來了革命性改進,尤其是擴展運算符和解構賦值,極大提升了開發(fā)體驗。
1. 擴展運算符
// 數(shù)組復制 const original = [1, 2, 3]; const copy = [...original]; // 數(shù)組合并 const arr1 = [1, 2]; const arr2 = [3, 4]; const merged = [...arr1, ...arr2]; // [1, 2, 3, 4] // 函數(shù)參數(shù) const numbers = [1, 2, 3]; Math.max(...numbers); // 3 // 添加元素 const newArr = [0, ...numbers, 4]; // [0, 1, 2, 3, 4]
說明:
- 擴展運算符
...可展開可迭代對象,語法簡潔,功能強大。- 廣泛用于淺拷貝、合并、函數(shù)傳參、插入元素等場景。
- 注意:僅支持淺拷貝,嵌套對象仍為引用。
2. 解構賦值
const arr = [1, 2, 3, 4, 5]; // 基本解構 const [first, second] = arr; // first = 1, second = 2 // 跳過元素 const [a, , c] = arr; // a = 1, c = 3 // 剩余元素 const [x, y, ...rest] = arr; // x = 1, y = 2, rest = [3, 4, 5] // 默認值 const [p = 10, q = 20] = [1]; // p = 1, q = 20 // 交換變量 let m = 1, n = 2; [m, n] = [n, m]; // m = 2, n = 1
說明:
- 解構賦值讓從數(shù)組中提取值變得極其簡潔。
- 支持跳過、剩余、默認值等高級語法。
- 常用于函數(shù)返回值、參數(shù)解構、變量交換等場景。
3. 新增靜態(tài)方法
// Array.isArray() - 類型檢查
Array.isArray([1, 2, 3]); // true
Array.isArray({}); // false
// Array.from() 的高級用法
const unique = Array.from(new Set([1, 2, 2, 3])); // 去重: [1, 2, 3]
// 創(chuàng)建范圍數(shù)組
const range = (start, end) =>
Array.from({ length: end - start + 1 }, (_, i) => start + i);
range(1, 5); // [1, 2, 3, 4, 5]說明:
Array.isArray()是判斷數(shù)組的唯一可靠方式(typeof無效)。Array.from()結合Set可實現(xiàn)去重,結合length可生成序列。range()函數(shù)是生成數(shù)字序列的常用工具。
十、性能優(yōu)化建議
合理選擇數(shù)組方法不僅能提升代碼可讀性,還能顯著改善性能,尤其是在處理大數(shù)據(jù)集時。
1. 方法選擇指南
// 1. 遍歷時不需要返回新數(shù)組:forEach > map // 正確 numbers.forEach(n => console.log(n)); // 2. 需要返回新數(shù)組:map > forEach + push // 推薦 const doubled = numbers.map(n => n * 2); // 不推薦 const doubled2 = []; numbers.forEach(n => doubled2.push(n * 2)); // 3. 查找元素:find > filter[0] // 推薦 users.find(u => u.id === 1); // 不推薦 users.filter(u => u.id === 1)[0]; // 4. 檢查存在性:some > find + Boolean // 推薦 users.some(u => u.age > 30); // 不推薦 Boolean(users.find(u => u.age > 30));
說明:
map()會創(chuàng)建新數(shù)組,若不需要應使用forEach()。filter()[0]會遍歷整個數(shù)組,而find()找到即停,性能更優(yōu)。some()語義更明確且短路求值,優(yōu)于find后轉布爾。
2. 避免常見陷阱
// 1. 稀疏數(shù)組
const sparse = new Array(5); // [empty × 5]
sparse.map(() => 1); // 仍然 [empty × 5]
// 解決方案
const dense = Array.from({ length: 5 }, () => 1); // [1, 1, 1, 1, 1]
// 2. 修改原數(shù)組的方法
const arr = [1, 2, 3];
const sorted = arr.sort(); // arr也被修改了!
// 解決方案
const sortedSafe = [...arr].sort(); // 或 arr.slice().sort()
// 3. 浮點數(shù)精度
[0.1, 0.2].reduce((a, b) => a + b); // 0.30000000000000004
// 解決方案
[0.1, 0.2].reduce((a, b) => a + b).toFixed(1); // "0.3"說明:
- 稀疏數(shù)組的
map、filter等方法會跳過空位,導致意外行為。sort()、reverse()、splice()等方法會修改原數(shù)組,需注意副作用。- 浮點數(shù)計算應使用
toFixed()或Math.round()處理精度問題。
3. 實用工具函數(shù)
// 數(shù)組去重
const unique = arr => [...new Set(arr)];
unique([1, 2, 2, 3, 1]); // [1, 2, 3]
// 數(shù)組分組
const groupBy = (arr, key) =>
arr.reduce((groups, item) => {
const group = groups[item[key]] || [];
return { ...groups, [item[key]]: [...group, item] };
}, {});
// 數(shù)組分塊
const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (_, i) =>
arr.slice(i * size, i * size + size)
);
// 數(shù)組隨機排序
const shuffle = arr =>
[...arr].sort(() => Math.random() - 0.5);說明:
Set去重簡潔高效,適用于基本類型。groupBy()利用reduce實現(xiàn)對象分組,常用于數(shù)據(jù)聚合。chunk()將數(shù)組分頁或分批處理。shuffle()實現(xiàn)洗牌,但sort()方式不夠隨機,生產環(huán)境建議用 Fisher-Yates 算法。
總結
這份總結涵蓋了 JavaScript 數(shù)組的核心操作方法,從基礎到高級,從傳統(tǒng)到現(xiàn)代。掌握這些方法將極大提升你的開發(fā)效率和代碼質量。建議在實際項目中多加練習,形成自己的使用習慣和最佳實踐。
到此這篇關于JavaScript 數(shù)組的核心操作方法,從基礎到高級的文章就介紹到這了,更多相關js數(shù)組基礎內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript新手必看之var在for循環(huán)中的坑
var這個關鍵字在JS當中是相當常用的,但同時配合到for循環(huán)的話會出現(xiàn)不符合預期的運行結果,所以本文就來為大家講講如何避免這種情況的出現(xiàn)2023-05-05
原生JS實現(xiàn)圖片輪播 JS實現(xiàn)小廣告插件
這篇文章主要為大家詳細介紹了原生JS實現(xiàn)圖片輪播、小廣告插件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09

