JS之Array構(gòu)造函數(shù)上的靜態(tài)方法與實(shí)例解讀
在 JavaScript 中,Array 既是一個(gè)構(gòu)造函數(shù),也是一個(gè)全局對(duì)象。它身上的方法分為兩類:靜態(tài)方法(直接通過(guò) Array.xxx 調(diào)用)和實(shí)例方法(通過(guò)數(shù)組實(shí)例 [].xxx 調(diào)用)。
一、 Array 實(shí)例方法
1.1 Array.prototype.at()
at() 方法接收一個(gè)整數(shù)值,并返回該索引對(duì)應(yīng)的元素。
1.1.1 語(yǔ)法與參數(shù)
參數(shù): index (整數(shù))。
- 正數(shù): 從左往右找(從 0 開(kāi)始)。
- 負(fù)數(shù): 從右往左找(從 -1 開(kāi)始)。
返回值: 對(duì)應(yīng)索引的元素。如果找不到(索引超限),則返回 undefined。
const arr = ['Apple', 'Banana', 'Cherry']; console.log(arr.at(0)); // "Apple" console.log(arr.at(-1)); // "Cherry" (倒數(shù)第一個(gè)) console.log(arr.at(-2)); // "Banana" (倒數(shù)第二個(gè)) console.log(arr.at(10)); // undefined
1.1.2 注意點(diǎn)
- 不僅僅是數(shù)組: 字符串 也能用。“Hello”.at(-1) 會(huì)返回 “o”。
- 非破壞性: 它只是讀取值,絕對(duì)不會(huì)像 splice 或 pop 那樣修改原數(shù)組。
1.1.3 類似實(shí)現(xiàn)方法
除了 at(),通常有以下幾種替代方案:
| 方案 | 示例 | 優(yōu)缺點(diǎn) |
|---|---|---|
| 方括號(hào)索引 | arr[arr.length - 1] | 最傳統(tǒng),但取末尾元素很麻煩。 |
| slice() | arr.slice(-1)[0] | 支持負(fù)數(shù),但它會(huì)創(chuàng)建一個(gè)新數(shù)組,性能略低,寫(xiě)起來(lái)也繞。 |
| pop() | arr.pop() | 能拿到最后一個(gè),但它會(huì)改變(刪除)原數(shù)組。 |
1.2 Array.prototype.concat()
Array.prototype.concat() 是 JavaScript 中最經(jīng)典、最常用的合并方法。
它的核心作用是將 兩個(gè)或多個(gè)數(shù)組(或值)連接成一個(gè)全新的數(shù)組。
1.2.1 語(yǔ)法與參數(shù)
const newArray = oldArray.concat(value1, value2, ..., valueN);
- 參數(shù): 可以是數(shù)組,也可以是具體的值(字符串、數(shù)字、對(duì)象等)。
- 返回值: 一個(gè)全新的數(shù)組實(shí)例,包含調(diào)用它的數(shù)組元素,以及按順序添加的所有參數(shù)元素。
- 非破壞性: 它不會(huì)修改原數(shù)組(oldArray 保持不變)。
1.2.2 使用場(chǎng)景
A. 合并多個(gè)數(shù)組
最直觀的用途,把碎片化的數(shù)據(jù)拼成大列表。
const digital = [1, 2]; const analog = [3, 4]; const alpha = ['a', 'b']; const combined = digital.concat(analog, alpha); // [1, 2, 3, 4, 'a', 'b']
B. 混合合并(值與數(shù)組)
你可以在合并數(shù)組的同時(shí),順手塞進(jìn)幾個(gè)散裝的值。
const base = [1, 2]; const result = base.concat(3, [4, 5]); // [1, 2, 3, 4, 5]
C. 淺拷貝數(shù)組(傳統(tǒng)做法)
const copy = arr.concat();
1.2.3 注意點(diǎn)
① 淺拷貝警告 (Shallow Copy)
concat 進(jìn)行的是 淺拷貝。如果數(shù)組里存的是對(duì)象,合并后的新數(shù)組和原數(shù)組指向的是同一個(gè)對(duì)象地址。修改其中一個(gè),另一個(gè)也會(huì)跟著變。
② 只能扁平化一層數(shù)組
concat 會(huì)自動(dòng)拆解參數(shù)中的第一層數(shù)組,但不會(huì)遞歸拆解。
const arr = [1].concat([2, [3, 4]]); // 結(jié)果是 [1, 2, [3, 4]],而不是 [1, 2, 3, 4]
如果需要完全拍平,請(qǐng)配合 flat() 方法使用。
1.2.4 類似實(shí)現(xiàn)方法
目前開(kāi)發(fā)中,concat 最強(qiáng)力的競(jìng)爭(zhēng)對(duì)手是 ES6 的 擴(kuò)展運(yùn)算符 (…)。
| 方法 | 示例 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|
| concat() | a.concat(b) | 語(yǔ)義明確;兼容性極好(ES3)。 | 語(yǔ)法略顯老舊。 |
| 擴(kuò)展運(yùn)算符 | “[…a, …b]” | 現(xiàn)代主流;更簡(jiǎn)潔;易于在中間插入值。 | 需要編譯(Babel)以支持舊環(huán)境。 |
| push(…others) | a.push(…b) | 性能極高(對(duì)于超大數(shù)組)。 | 會(huì)改變?cè)瓟?shù)組 a。 |
1.3 Array.prototype.constructor
在 JavaScript 中,每個(gè)對(duì)象都有一個(gè) constructor 屬性,指向創(chuàng)建該實(shí)例對(duì)象的構(gòu)造函數(shù)。
- 參數(shù): 無(wú)(它是一個(gè)屬性,不是一個(gè)需要傳入?yún)?shù)執(zhí)行的方法,盡管你可以像函數(shù)一樣調(diào)用它)。
- 返回值: 返回對(duì)創(chuàng)建了該數(shù)組實(shí)例的 Array 構(gòu)造函數(shù)的引用。
- 本質(zhì): [].constructor === Array 返回 true。
1.3.1 為什么要引入這個(gè)屬性?(核心意義)
在面向?qū)ο缶幊蹋∣OP)中,constructor 的存在是為了讓實(shí)例能夠溯源。
- 識(shí)別身份: 知道這個(gè)對(duì)象是從哪個(gè)“模具”里出來(lái)的。
- 動(dòng)態(tài)創(chuàng)建: 如果你手里有一個(gè)實(shí)例 a,但你不知道它的具體類型,你可以通過(guò) a.constructor 來(lái)創(chuàng)建一個(gè)和它同類型的新實(shí)例,而不需要硬編碼類名。
1.3.2 使用場(chǎng)景
A. 準(zhǔn)確判斷類型
雖然現(xiàn)在流行用 Array.isArray(),但在處理自定義類時(shí),constructor 非常有用。
const arr = [1, 2, 3];
if (arr.constructor === Array) {
console.log("這是一個(gè)數(shù)組");
}
B. 基于現(xiàn)有實(shí)例創(chuàng)建新實(shí)例
當(dāng)你編寫(xiě)一個(gè)通用的函數(shù),需要返回一個(gè)與輸入對(duì)象類型相同的新對(duì)象時(shí):
function cloneEmpty(obj) {
// 無(wú)論傳進(jìn)來(lái)的是 Array 還是自定義的 MyArray,都能創(chuàng)建正確的類型
return new obj.constructor();
}
const newArr = cloneEmpty([1, 2, 3]); // 返回 []
1.4 Array.prototype.copyWithin() - 破壞性
它的行為像是在數(shù)組內(nèi)部進(jìn)行了一次 “復(fù)制 + 粘貼”。
1.4.1 語(yǔ)法與參數(shù)
arr.copyWithin(target, start, end); // 左閉右開(kāi)
- target (必填):復(fù)制到的目標(biāo)索引位置。如果是負(fù)數(shù),則從末尾開(kāi)始計(jì)算。
- start (可選):開(kāi)始復(fù)制的源元素索引(默認(rèn)為 0)。
- end (可選):結(jié)束復(fù)制的源元素索引(不包含該索引,默認(rèn)為 arr.length)。
- 返回值:返回修改后的數(shù)組(不產(chǎn)生新數(shù)組)。
const arr = [1, 2, 3, 4, 5]; // 把索引 3 到 4 的元素(也就是數(shù)字 4),復(fù)制到索引 0 的位置 const result = arr.copyWithin(0, 3, 4); console.log(arr); // 輸出: [4, 2, 3, 4, 5] console.log(result); // 輸出: [4, 2, 3, 4, 5] console.log(arr === result); // 輸出: true (指向同一個(gè)內(nèi)存地址)
1.4.2 行為特征(重點(diǎn))
- 修改原數(shù)組:它直接在原數(shù)組上操作,不產(chǎn)生新數(shù)組。
- 長(zhǎng)度不變:它不會(huì)改變數(shù)組的 length。如果復(fù)制的內(nèi)容超出了數(shù)組末尾,多余的部分會(huì)被截?cái)唷?/li>
- 高性能:它在內(nèi)存內(nèi)部移動(dòng)數(shù)據(jù),速度非??臁?/li>
由于 copyWithin 始終維持原數(shù)組的 length,它就像是在一個(gè)固定長(zhǎng)度的容器里挪動(dòng)?xùn)|西:如果挪過(guò)去的東西太長(zhǎng),放不下的部分就會(huì)被“擠出去”丟掉。
const arr = ['a', 'b', 'c', 'd', 'e']; // 目標(biāo)位置 (target): 3 // 開(kāi)始讀取 (start): 0 // 結(jié)束讀取 (end): 默認(rèn)到末尾 (索引 5) // 復(fù)制的內(nèi)容本應(yīng)是: ['a', 'b', 'c', 'd', 'e'] (長(zhǎng)度為 5) arr.copyWithin(3, 0); console.log(arr); // 輸出: ["a", "b", "c", "a", "b"] // 數(shù)組長(zhǎng)度依然是: 5
1.5 Array.prototype.entries()
它主要用于將數(shù)組轉(zhuǎn)換為一個(gè)可迭代的對(duì)象,方便我們?cè)诒闅v時(shí)同時(shí)獲取“索引”和“值”。
1.5.1 語(yǔ)法與參數(shù)
const iterator = arr.entries();
- 參數(shù): 無(wú)。
- 返回值: 返回一個(gè)新的 Array Iterator(數(shù)組迭代器) 對(duì)象。
- 內(nèi)容: 該迭代器每迭代一步,都會(huì)返回一個(gè)數(shù)組 [index, element]
1.5.2 為什么要引入這個(gè)方法?
在 entries() 出現(xiàn)之前,JavaScript 遍歷數(shù)組面臨兩難選擇:
- for 循環(huán): 能拿到索引 i,但語(yǔ)法繁瑣。
- forEach(): 能同時(shí)拿索引和值,但無(wú)法使用 break 或 continue 跳出循環(huán)。
- for…of: 語(yǔ)法最簡(jiǎn)潔,但默認(rèn)只能拿到值,拿不到索引。
引入意義: entries() 讓 for…of 能夠以極其優(yōu)雅的方式同時(shí)獲取 索引 和 值。
數(shù)組本身確實(shí)是可迭代的。當(dāng)你直接使用 for…of 遍歷數(shù)組時(shí),它默認(rèn)調(diào)用的是數(shù)組的 values() 方法。只能拿到值,拿不到索引。

1.5.3 使用場(chǎng)景
A. 在 for…of 中獲取索引(最常用)
const fruits = ['Apple', 'Banana', 'Cherry'];
for (const [index, value] of fruits.entries()) {
console.log(`第 ${index} 個(gè)水果是 ${value}`);
}
B. 處理稀疏數(shù)組
entries() 會(huì)遍歷數(shù)組中的“空洞”(holes),并將其值視為 undefined。這比 forEach 更嚴(yán)謹(jǐn),因?yàn)?forEach 會(huì)直接跳過(guò)空單元。
const sparse = [1, , 3];
for (const [i, v] of sparse.entries()) {
console.log(i, v); // 輸出: 0 1, 1 undefined, 2 3
}
C. 快速將數(shù)組轉(zhuǎn)為 Map
const arr = ['a', 'b', 'c'];
const map = new Map(arr.entries());
// Map(3) { 0 => 'a', 1 => 'b', 2 => 'c' }
1.6 Array.prototype.every()
它的核心作用是:檢查數(shù)組中的 所有 元素是否都符合某個(gè)條件。
1.6.1 語(yǔ)法與參數(shù)
const allPassed = arr.every(callbackFn(element, index, array), thisArg);
callbackFn (回調(diào)函數(shù)):對(duì)每個(gè)元素執(zhí)行的函數(shù),返回 true 表示通過(guò),false 表示失敗。
- element:當(dāng)前正在處理的元素。
- index:當(dāng)前元素的索引。
- array:調(diào)用 every 的原數(shù)組。
thisArg (可選):執(zhí)行回調(diào)時(shí)用作 this 的值。
返回值:布爾值 (true 或 false)。
1.6.2 行為特征:短路機(jī)制 (Short-circuiting)
every() 非常聰明。它不需要遍歷完整個(gè)數(shù)組:
- 只要發(fā)現(xiàn)一個(gè)元素不符合條件,它會(huì)立即返回 false 并停止遍歷。
- 只有當(dāng)所有元素都返回 true 時(shí),它才會(huì)返回 true。
1.6.3 避坑指南
① 空數(shù)組陷阱 (重點(diǎn)!)
對(duì)于空數(shù)組 [],every() 總是返回 true。
這被稱為“空真理”(Vacuous truth)。邏輯依據(jù)是:在一個(gè)空集合中,沒(méi)有任何元素違反條件。
[].every(x => x > 10); // true!
② 非破壞性:它不會(huì)修改原數(shù)組。
1.7 Array.prototype.fill() - 破壞性
它能用一個(gè)固定值填充數(shù)組的全部或部分。
1.7.1 語(yǔ)法與參數(shù)
arr.fill(value, start, end);
- value (必填):填充數(shù)組的值。
- start (可選):開(kāi)始填充的起始索引(默認(rèn)為 0)。
- end (可選):結(jié)束填充的索引(不包含該索引,默認(rèn)為 arr.length)。
- 返回值:返回修改后的原數(shù)組。
1.7.2 使用場(chǎng)景
A. 快速初始化數(shù)組
這是最常見(jiàn)的用法,配合 new Array() 使用:
const grades = new Array(5).fill(100); // [100, 100, 100, 100, 100]
B. 重置部分?jǐn)?shù)組數(shù)據(jù)
將數(shù)組中索引 1 到 3 的元素清零:
const data = [10, 20, 30, 40, 50]; data.fill(0, 1, 4); // [10, 0, 0, 0, 50]
1.7.3 避坑指南
① 引用類型陷阱
這是 fill() 最容易翻車的地方。 如果填充的值是一個(gè)對(duì)象或數(shù)組,那么數(shù)組里的所有元素都會(huì)指向同一個(gè)內(nèi)存地址(淺拷貝)。
const arr = new Array(3).fill({ name: 'Gemini' });
arr[0].name = 'AI';
console.log(arr[1].name); // 也是 'AI'!因?yàn)樗鼈兪峭粋€(gè)對(duì)象。
② 改變?cè)瓟?shù)組
fill() 會(huì)直接修改調(diào)用它的數(shù)組,而不是返回副本。
1.8 Array.prototype.filter()
Array.prototype.filter() 是 JavaScript 中最常用的數(shù)據(jù)篩選工具。它的核心作用是:從原數(shù)組中挑出符合條件的元素,并組成一個(gè)新數(shù)組。
1.8.1 語(yǔ)法與參數(shù)
const newArray = arr.filter(callbackFn(element, index, array), thisArg);
callbackFn (回調(diào)函數(shù)):對(duì)每個(gè)元素執(zhí)行的測(cè)試函數(shù)。
- 返回 true:保留該元素。
- 返回 false:丟棄該元素。
返回值:一個(gè)包含所有通過(guò)測(cè)試的元素的新數(shù)組。如果沒(méi)有元素通過(guò)測(cè)試,則返回空數(shù)組 []。
const products = [
{ name: 'iPhone', price: 800 },
{ name: 'Case', price: 20 }
];
const expensive = products.filter(p => p.price > 100);
// [{ name: 'iPhone', price: 800 }]
1.8.2 避坑指南
- 非破壞性:它永遠(yuǎn)不會(huì)改變?cè)瓟?shù)組,而是返回一個(gè)副本。
- 淺拷貝:如果數(shù)組包含對(duì)象,filter 返回的新數(shù)組里存的是相同的引用。修改新數(shù)組中的對(duì)象,原數(shù)組的對(duì)象也會(huì)變。
- 稀疏數(shù)組:它不會(huì)為缺少的元素(空洞)執(zhí)行回調(diào)。
1.9 Array.prototype.find()
Array.prototype.find() 是 JavaScript 中用于定位單個(gè)元素的高階方法。它的核心作用是:返回?cái)?shù)組中滿足條件的第一個(gè)元素的值。
1.9.1 語(yǔ)法與參數(shù)
const foundElement = arr.find(callbackFn(element, index, array), thisArg);
callbackFn (回調(diào)函數(shù)):對(duì)每個(gè)元素執(zhí)行的測(cè)試函數(shù)。
- 返回 true:表示找到了,停止查找并返回該元素。
- 返回 false:繼續(xù)找下一個(gè)。
返回值:數(shù)組中第一個(gè)通過(guò)測(cè)試的元素值。如果沒(méi)有任何元素符合條件,則返回 undefined。
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const user = users.find(u => u.id === 2);
// { id: 2, name: 'Bob' }
1.9.2 避坑指南
- 只找一個(gè):它只返回第一個(gè)匹配項(xiàng)。如果你需要找所有匹配項(xiàng),請(qǐng)使用 filter()。
- 找不到返回 undefined:使用返回值前,最好先做個(gè)非空判斷,避免 Cannot read property of undefined。
- 無(wú)法區(qū)分“未找到”和“值為 undefined”:如果數(shù)組本身包含 undefined 且符合條件,find 也會(huì)返回 undefined。
- 非破壞性:不改變?cè)瓟?shù)組。
1.10 Array.prototype.findIndex()
Array.prototype.findIndex() 是 find() 的親兄弟。區(qū)別在于:find() 返回元素本身,而 findIndex() 返回該元素在數(shù)組中的位置(索引)。
1.10.1 語(yǔ)法與參數(shù)
const index = arr.findIndex(callbackFn(element, index, array), thisArg);
callbackFn (回調(diào)函數(shù)):測(cè)試函數(shù)。
- 返回 true:停止搜索,返回當(dāng)前索引。
- 返回 false:繼續(xù)找下一個(gè)。
返回值:返回第一個(gè)符合條件的元素的索引(從 0 開(kāi)始)。如果沒(méi)有任何元素符合條件,則返回 -1。
const users = [{id: 1, name: 'A'}, {id: 2, name: 'B'}, {id: 3, name: 'C'}];
const index = users.findIndex(u => u.id === 2);
if (index !== -1) {
users.splice(index, 1); // 成功刪除 'B'
}
1.10.2 避坑指南
- 找不到返回 -1:這是和 find() 最明顯的區(qū)別(find 找不到返回 undefined)。在做后續(xù)操作(如 splice)前,一定要判斷是否等于 -1,否則 splice(-1, 1) 會(huì)刪掉數(shù)組的最后一個(gè)元素!
- 短路特性:一旦找到符合條件的,后面剩下的元素就不會(huì)再遍歷了。
- 非破壞性:它只負(fù)責(zé)“看”,不負(fù)責(zé)“改”。
1.10.2 類似實(shí)現(xiàn)方法
| 方法 | 返回值 | 適用場(chǎng)景 |
|---|---|---|
| indexOf() | 索引 | 僅限于查找簡(jiǎn)單的原始類型(如數(shù)字、字符串)。 |
| find() | 元素本身 | 當(dāng)你只需要獲取數(shù)據(jù),而不需要它的索引位置時(shí)。 |
| lastIndexOf() | 索引 | 從后往前找第一個(gè)符合條件的索引(僅限簡(jiǎn)單值)。 |
| findLastIndex() | 索引 | ES2023 引入,支持從后往前通過(guò)回調(diào)函數(shù)找索引。 |
1.11 Array.prototype.findLast()
它的功能與 find() 完全一樣,唯一的區(qū)別在于它的查找方向:它從數(shù)組的最后一個(gè)元素開(kāi)始反向遍歷。
1.11.1 語(yǔ)法與參數(shù)
const found = arr.findLast(callbackFn(element, index, array), thisArg);
- 參數(shù):與 find() 一致,接收一個(gè)回調(diào)函數(shù)(元素、索引、數(shù)組實(shí)例)和一個(gè)可選的 this 指向。
- 返回值:返回倒數(shù)第一個(gè)符合條件的元素。如果沒(méi)有任何元素符合條件,則返回 undefined。
const timeline = [
{ id: 1, action: 'login', time: '10:00' },
{ id: 2, action: 'post', time: '10:05' },
{ id: 3, action: 'login', time: '10:10' }
];
// 查找最后一次登錄的信息
const lastLogin = timeline.findLast(item => item.action === 'login');
// { id: 3, action: 'login', time: '10:10' }
1.12 Array.prototype.findLastIndex()
它是 findIndex() 的反向版本:從數(shù)組末尾開(kāi)始向前搜索,返回第一個(gè)符合條件的元素的索引。
1.12.1 語(yǔ)法與參數(shù)
const index = arr.findLastIndex(callbackFn(element, index, array), thisArg);
參數(shù):接收一個(gè)回調(diào)函數(shù)(當(dāng)前元素、當(dāng)前索引、數(shù)組本身)以及一個(gè)可選的 this 指向。
返回值:
- 返回滿足條件的最后一個(gè)(從后往前數(shù)第一個(gè))元素的正向索引。
- 如果沒(méi)有任何元素符合條件,則返回 -1。
const logs = [
{ type: 'save', id: 101 },
{ type: 'edit', id: 102 },
{ type: 'save', id: 103 },
{ type: 'edit', id: 104 }
];
// 找到最后一次 'save' 類型操作的索引
const lastSaveIndex = logs.findLastIndex(item => item.type === 'save');
console.log(lastSaveIndex); // 2
1.12.2 避坑指南
- 索引仍然是正向的:即使是反向遍歷,返回的索引值依然是基于數(shù)組開(kāi)頭的(0, 1, 2…)。
- 非破壞性:它不會(huì)修改原數(shù)組。
1.13 Array.prototype.flat()
它的核心作用是:按照指定的深度遞歸遍歷數(shù)組,將子數(shù)組中的元素合并到新數(shù)組中,俗稱 “數(shù)組拍平”。
1.13.1 語(yǔ)法與參數(shù)
const newArray = arr.flat(depth);
depth (可選):指定要提取嵌套數(shù)組的結(jié)構(gòu)深度。
- 默認(rèn)為 1。
- 如果傳入 Infinity,則無(wú)論嵌套多少層都會(huì)被拍平。
返回值:一個(gè)包含所有子數(shù)組元素組成的新數(shù)組。
const nested = [1, [2, [3, 4]]]; console.log(nested.flat()); // [1, 2, [3, 4]] (默認(rèn)深度為1) console.log(nested.flat(2)); // [1, 2, 3, 4]
徹底拍平(不管嵌套多深)當(dāng)你處理來(lái)源不明、嵌套層級(jí)混亂的數(shù)據(jù)時(shí):
const crazy = [1, [2, [3, [4, [5]]]]]; const flatResult = crazy.flat(Infinity); // [1, 2, 3, 4, 5]
1.13.2 避坑指南
- 非破壞性:它返回一個(gè)新數(shù)組,原數(shù)組保持不變。
- 淺拷貝:拍平過(guò)程中,如果元素是對(duì)象,復(fù)制的依然是引用地址。
1.14 Array.prototype.flatMap()
它就是 map() 和 flat(1) 的組合體,但它比手動(dòng)鏈?zhǔn)秸{(diào)用這兩者更高效。
1.14.1 語(yǔ)法與參數(shù)
const newArray = arr.flatMap(callbackFn(element, index, array), thisArg);
- callbackFn (回調(diào)函數(shù)):與 map 相同,但在映射后,它會(huì)對(duì)返回的結(jié)果自動(dòng)進(jìn)行 一層(深度為 1) 的拍平。
- 返回值:一個(gè)新的數(shù)組,其中每個(gè)元素都是回調(diào)函數(shù)結(jié)果被拍平后的產(chǎn)物。
const orders = [
{ id: 1, items: ["蘋(píng)果", "香蕉"] },
{ id: 2, items: ["橙子"] },
{ id: 3, items: ["西瓜", "葡萄"] }
];
const res = orders.flatMap(order => order.items);
console.log(res);
// 結(jié)果是:["蘋(píng)果", "香蕉", "橙子", "西瓜", "葡萄"]
// 直接拿到了干凈的商品清單!
1.14.2 避坑指南
- 只能拍平一層:這是 flatMap 與 flat(depth) 的最大區(qū)別。如果你的回調(diào)函數(shù)返回的是一個(gè)三層嵌套數(shù)組,它只會(huì)把它變成兩層。
- 效率優(yōu)于鏈?zhǔn)秸{(diào)用:arr.flatMap(f) 比 arr.map(f).flat() 快,因?yàn)樗恍枰獎(jiǎng)?chuàng)建中間的臨時(shí)數(shù)組。
- 非破壞性:它不修改原數(shù)組。
1.15 Array.prototype.forEach()
Array.prototype.forEach()是JavaScript 中最基礎(chǔ)、最常用的遍歷方法。它的核心作用是:對(duì)數(shù)組的每個(gè)元素執(zhí)行一次給定的函數(shù)。
1.15.1 語(yǔ)法與參數(shù)
arr.forEach(callbackFn(element, index, array), thisArg);
callbackFn(回調(diào)函數(shù)):為每個(gè)元素執(zhí)行的函數(shù)。
- element:當(dāng)前遍歷到的元素。
- index:當(dāng)前元素的索引。
- array:正在處理的原數(shù)組。
- thisArg(可選):執(zhí)行回調(diào)時(shí)用作this的值。
返回值:undefined。它不返回任何有意義的結(jié)果,本質(zhì)上是一個(gè)“過(guò)程控制”工具。
const items = ['apple', 'banana'];
const copy = [];
items.forEach(item => {
copy.push(item.toUpperCase()); // 操作外部變量
});
1.15.2 避坑指南
① 無(wú)法中斷(不可break/continue)
這是它最大的痛點(diǎn)。 forEach一旦開(kāi)始,除非拋出異常,否則它會(huì)遍歷完數(shù)組中的所有元素。
- 如果你需要中斷循環(huán):請(qǐng)使用傳統(tǒng)的for循環(huán)、for…of、或者some()/ every()。
② 異步陷阱
forEach不會(huì)等待異步函數(shù)(如Promise)完成。它會(huì)像機(jī)關(guān)槍一樣瞬間打完所有回調(diào),而不理會(huì)內(nèi)部的await。
- 解決方法:使用for…of配合await。
// 錯(cuò)誤示例
arr.forEach(async (item) => {
await someAsyncCall(item); // 這里不會(huì)按順序等待
});
1.16 Array.prototype.includes()
它的核心作用是:判斷一個(gè)數(shù)組是否包含一個(gè)指定的值,根據(jù)情況返回true或false。
1.16.1 語(yǔ)法與參數(shù)
const hasValue = arr.includes(searchElement, fromIndex);
searchElement(必填):需要查找的元素值。
fromIndex(可選):從哪個(gè)索引處開(kāi)始查找。
- 如果是負(fù)數(shù),則從array.length + fromIndex的位置開(kāi)始。
- 默認(rèn)為0。
返回值:布爾值( true/ false)。
const fruits = ['apple', 'banana', 'mango'];
// 1. 基本用法
console.log(fruits.includes('banana')); // true
console.log(fruits.includes('grape')); // false
// 2. 第二個(gè)參數(shù):起始查找位置
console.log(fruits.includes('apple', 1)); // false (從索引1開(kāi)始找,找不到apple)
// 3. 完美處理 NaN
const arr = [1, 2, NaN];
console.log(arr.indexOf(NaN)); // -1 (舊方法的坑)
console.log(arr.includes(NaN)); // true (ES7 正確識(shí)別)
1.16.2 避坑指南
- 無(wú)法查找“深層”對(duì)象:由于它是通過(guò)值/引用地址來(lái)對(duì)比的,所以它無(wú)法直接查找對(duì)象內(nèi)容。
- 提示:查找對(duì)象是否存在,請(qǐng)使用some()或find()。
- 大小寫(xiě)敏感:對(duì)于字符串?dāng)?shù)組,includes()是嚴(yán)格區(qū)分大小寫(xiě)的。
1.17 Array.prototype.indexOf()
Array.prototype.indexOf()是JavaScript 中最經(jīng)典的索引查找方法。它的核心作用是:從數(shù)組中尋找指定元素,并返回它第一次出現(xiàn)的位置索引。
1.17.1 語(yǔ)法與參數(shù)
const index = arr.indexOf(searchElement, fromIndex);
- searchElement(必填):要查找的元素。
- fromIndex(可選):開(kāi)始查找的位置。
如果是負(fù)數(shù),則表示從倒數(shù)第幾個(gè)開(kāi)始找(但查找方向依然是從左往右)。
返回值:
- 找到則返回該元素的第一個(gè)索引(數(shù)字)。
- 找不到則返回-1。
const beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
console.log(beasts.indexOf('bison')); // 1
console.log(beasts.indexOf('bison', 2)); // 4 (從索引2開(kāi)始找)
if (arr.indexOf('something') !== -1) {
// 元素存在
}
const unique = arr.filter((item, index) => arr.indexOf(item) === index); // 只有當(dāng)元素的“第一次出現(xiàn)索引”等于“當(dāng)前遍歷索引”時(shí),才保留它
1.17.2 避坑指南
嚴(yán)格相等與NaN:indexOf使用的是嚴(yán)格相等( ===)。這導(dǎo)致它有兩個(gè)局限:
- 無(wú)法識(shí)別NaN:[NaN].indexOf(NaN)會(huì)返回-1。
- 對(duì)象查找:只有引用地址完全一致才能找到。
只能找“第一個(gè)”:如果數(shù)組中有重復(fù)元素,它只會(huì)返回最左邊的那一個(gè)。如果你想找最后一個(gè),請(qǐng)使用lastIndexOf()。
1.18 Array.prototype.join()
用于將數(shù)組轉(zhuǎn)換為字符串的核心方法。它的作用是將數(shù)組的所有元素連接起來(lái),并在元素之間插入指定的連接符。
1.18.1 語(yǔ)法與參數(shù)
const str = arr.join(separator);
separator(可選):指定連接每個(gè)元素的字符串。
如果省略,默認(rèn)使用逗號(hào)( ,)。
如果傳入空字符串( “”),元素之間將沒(méi)有任何字符。
返回值:一個(gè)包含所有數(shù)組元素連接而成的新字符串。如果數(shù)組長(zhǎng)度為0,則返回空字符串。
const elements = ['Fire', 'Air', 'Water'];
console.log(elements.join()); // "Fire,Air,Water"
console.log(elements.join(' - ')); // "Fire - Air - Water"
1.18.2 避坑指南
① 自動(dòng)類型轉(zhuǎn)換
如果數(shù)組中的元素不是字符串,join()會(huì)隱式調(diào)用它們的toString()方法。
null和undefined:會(huì)被轉(zhuǎn)換成空字符串( “”) 。
[1, null, undefined, 4].join('-'); // "1---4"
1.19 Array.prototype.keys()
Array.prototype.keys()是ES6 引入的方法,它與entries()和values()屬于同一個(gè)迭代器家族。它的核心作用是:返回一個(gè)包含數(shù)組中所有 索引(鍵) 的可迭代對(duì)象。
1.19.1 語(yǔ)法與參數(shù)
const iterator = arr.keys();
參數(shù):無(wú)。
返回值:返回一個(gè)新的Array Iterator對(duì)象,該對(duì)象按順序包含數(shù)組的每一個(gè)索引值。
const arr = ['a', 'b', 'c'];
for (const key of arr.keys()) {
console.log(key); // 輸出: 0, 1, 2
}
const range = [...Array(5).keys()]; // [0, 1, 2, 3, 4]
1.19.2 避坑指南
它是迭代器:就像entries()一樣,你不能直接用arr.keys()[0]訪問(wèn)。你需要通過(guò)for…of遍歷,或者用[…iter]、Array.from(iter)轉(zhuǎn)換成真正的數(shù)組。
非破壞性:不會(huì)改變?cè)瓟?shù)組。
1.20 Array.prototype.lastIndexOf()
是indexOf()的“倒序版本”。它的核心作用是:從數(shù)組的末尾開(kāi)始向前搜索,返回指定元素最后一次出現(xiàn)的位置索引。
1.20.1 語(yǔ)法與參數(shù)
const index = arr.lastIndexOf(searchElement, fromIndex);
searchElement(必填):要查找的元素。
fromIndex(可選):開(kāi)始反向查找的位置。
默認(rèn)為arr.length - 1(即從最后一個(gè)元素開(kāi)始找)。
如果是負(fù)數(shù),則表示從倒數(shù)第幾個(gè)位置開(kāi)始向前找。
返回值:
找到則返回該元素的最后一個(gè)索引。
找不到則返回-1。
const numbers = [2, 5, 9, 2]; console.log(numbers.lastIndexOf(2)); // 3 console.log(numbers.lastIndexOf(7)); // -1 console.log(numbers.lastIndexOf(2, 2)); // 0 (從索引2開(kāi)始往前找)
通過(guò)對(duì)比indexOf和lastIndexOf的結(jié)果,可以快速判斷一個(gè)元素是否在數(shù)組中出現(xiàn)了多次:
const isDuplicate = (arr, val) => arr.indexOf(val) !== arr.lastIndexOf(val); isDuplicate([1, 2, 3, 2], 2); // true
1.20.2 避坑指南
① 查找方向
雖然fromIndex可以指定起點(diǎn),但查找的方向永遠(yuǎn)是向左(遞減)。
舉例:[2, 5, 9].lastIndexOf(9, 1)會(huì)返回-1,因?yàn)閺乃饕? (數(shù)字5) 開(kāi)始往回找,根本碰不到索引2 上的數(shù)字9。
② 嚴(yán)格相等(===)
與indexOf一樣,它使用嚴(yán)格相等:
無(wú)法識(shí)別NaN。
無(wú)法通過(guò)屬性查找對(duì)象(除非引用地址完全一致)。
1.21 Array.prototype.map()
它的核心作用是:創(chuàng)建一個(gè)新數(shù)組,其結(jié)果是原數(shù)組中的每個(gè)元素都調(diào)用一次提供的函數(shù)后的返回值。
1.21.1 語(yǔ)法與參數(shù)
const newArray = arr.map(callbackFn(element, index, array), thisArg);
callbackFn(回調(diào)函數(shù)) :生成新數(shù)組元素的函數(shù)。
element:當(dāng)前正在處理的元素。
index:當(dāng)前元素的索引。
返回值:一個(gè)由每次callbackFn返回的結(jié)果組成的新數(shù)組。
const users = [
{ id: 1, name: 'Alice', email: 'a@test.com' },
{ id: 2, name: 'Bob', email: 'b@test.com' }
];
const names = users.map(user => user.name);
// ['Alice', 'Bob']
const prices = [10, 20, 30]; const discounted = prices.map(p => p * 0.8); // [8, 16, 24]
1.21.2 避坑指南
- 必須有return:如果你的回調(diào)函數(shù)里忘記寫(xiě)return,新數(shù)組里的對(duì)應(yīng)位置就會(huì)是undefined。
1.22 Array.prototype.pop() - 破壞性
它的核心作用是:從數(shù)組中刪除最后一個(gè)元素,并返回該元素的值。
1.22.1 語(yǔ)法與參數(shù)
const lastElement = arr.pop();
參數(shù):無(wú)。
返回值:
返回從數(shù)組中刪除的那個(gè)元素。
如果數(shù)組是空的,則返回undefined。
副作用:此方法會(huì)改變?cè)瓟?shù)組(修改數(shù)組的length屬性)。
const history = ['home', 'settings', 'profile']; const lastPage = history.pop(); console.log(lastPage); // 'profile' console.log(history); // ['home', 'settings']
1.22.2 避坑指南
- 破壞性方法:它會(huì)直接修改你的原始數(shù)據(jù)。如果你需要保留原數(shù)組,請(qǐng)先使用[…arr]進(jìn)行淺拷貝。
- 空數(shù)組調(diào)用:在空數(shù)組上調(diào)用不會(huì)報(bào)錯(cuò),但會(huì)返回undefined。如果你的數(shù)組里本就存有undefined,需要小心區(qū)分是“取出的值”還是“數(shù)組已空”。
- 性能優(yōu)勢(shì):在大型數(shù)組中,pop()的執(zhí)行速度極快( O ( 1 ) O(1) O(1)),因?yàn)椴簧婕霸匚灰啤?/li>
1.23 Array.prototype.push() - 破壞性
它的核心作用是:將一個(gè)或多個(gè)元素添加到數(shù)組的末尾。
1.23.1 語(yǔ)法與參數(shù)
const newLength = arr.push(element1, element2, ..., elementN);
參數(shù):想要添加到數(shù)組末尾的元素(可以是一個(gè),也可以是多個(gè))。
返回值:添加新元素后數(shù)組的最新長(zhǎng)度 (length)。
副作用:此方法會(huì)改變?cè)瓟?shù)組(In-place mutation)。
const list1 = ['a', 'b']; const list2 = ['c', 'd']; list1.push(...list2); // list1 變?yōu)?['a', 'b', 'c', 'd']
1.23.2 避坑指南
- 小心返回值:新手最常犯的錯(cuò)誤是以為 push 返回的是修改后的數(shù)組。
- const result = arr.push(1); 得到的 result 是 1 (長(zhǎng)度),而不是 [… , 1]。
- 破壞性:它會(huì)直接修改你的原始數(shù)據(jù)。在 React 或 Redux 等狀態(tài)管理框架中,通常應(yīng)避免使用 push,而改用展開(kāi)運(yùn)算符:setItems([…items, newItem])。
1.24 Array.prototype.reduce()
的核心作用是:將數(shù)組中的所有元素通過(guò)一個(gè)累加器(accumulator)函數(shù),最終計(jì)算為一個(gè)單一的值。
1.24.1 語(yǔ)法與參數(shù)
const result = arr.reduce(callbackFn(accumulator, currentValue, currentIndex, array), initialValue);
callbackFn (累加器函數(shù)):
accumulator (累計(jì)器):上一次回調(diào)運(yùn)行的結(jié)果。
currentValue (當(dāng)前值):數(shù)組中正在處理的元素。
initialValue (初始值 - 建議必填):
第一次調(diào)用回調(diào)函數(shù)時(shí) accumulator 的值。
注意:如果不提供,則 accumulator 默認(rèn)為數(shù)組的第一個(gè)元素,且跳過(guò)第一次循環(huán)。
const nums = [1, 2, 3, 4]; const sum = nums.reduce((acc, curr) => acc + curr, 0); // 結(jié)果: 10
將數(shù)組轉(zhuǎn)換為對(duì)象 (數(shù)據(jù)聚合)
這是 reduce 的殺手锏,比如統(tǒng)計(jì)單詞出現(xiàn)次數(shù):
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const count = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
// 結(jié)果: { apple: 3, banana: 2, orange: 1 }
數(shù)組去重
雖然 Set 更快,但 reduce 展現(xiàn)了邏輯的靈活性:
const arr = [1, 2, 1, 3, 2, 4];
const unique = arr.reduce((acc, curr) => {
if (!acc.includes(curr)) acc.push(curr);
return acc;
}, []);
1.24.2 避坑指南
- 一定要 return:回調(diào)函數(shù)如果沒(méi)有 return,下一次循環(huán)的 accumulator 就會(huì)變成 undefined。
1.25 Array.prototype.reduceRight()
它的核心邏輯與 reduce() 完全一致,唯一的區(qū)別在于遍歷方向:它從數(shù)組的 最后一個(gè)元素開(kāi)始,向前(向左) 執(zhí)行累加操作。
1.25.1 語(yǔ)法與參數(shù)
const result = arr.reduceRight(callbackFn(accumulator, currentValue, currentIndex, array), initialValue);
遍歷順序:從 index = arr.length - 1 開(kāi)始,到 index = 0 結(jié)束。
參數(shù):與 reduce() 完全相同(累加器、當(dāng)前值、索引、原數(shù)組,以及可選的初始值)。
返回值:通過(guò)累加器函數(shù)計(jì)算得到的單一值。
const words = ["World", "Hello"]; const sentence = words.reduceRight((acc, curr) => acc + " " + curr); // 結(jié)果: "Hello World" (從右側(cè) "Hello" 開(kāi)始,加上 "World")
1.26 Array.prototype.reverse() - 破壞性
Array.prototype.reverse() 是一個(gè)非常直觀的方法,用于將數(shù)組中元素的順序顛倒。它是處理排序邏輯和視圖轉(zhuǎn)換時(shí)的常用工具。
1.26.1 語(yǔ)法與參數(shù)
const reversedArray = arr.reverse();
參數(shù):無(wú)。
返回值:指向原數(shù)組的引用。
副作用:破壞性方法。它會(huì)直接修改原始數(shù)組,而不是創(chuàng)建一個(gè)副本。
切換排序順序
配合 sort() 使用,可以實(shí)現(xiàn)降序排列(雖然 sort 自身也能實(shí)現(xiàn),但 reverse 更語(yǔ)義化):
const numbers = [1, 2, 3, 4, 5]; numbers.reverse(); // [5, 4, 3, 2, 1]
1.26.2 避坑指南
① 原地修改 (In-place)
- 這是 reverse 最容易被忽視的特性。它會(huì)改變?cè)瓟?shù)組:
const a = [1, 2, 3]; const b = a.reverse(); console.log(a); // [3, 2, 1] —— 原數(shù)組被改了! console.log(b === a); // true —— 它們指向同一個(gè)內(nèi)存地址
如果你需要保留原數(shù)組,請(qǐng)先使用展開(kāi)運(yùn)算符進(jìn)行拷貝:
const safeReversed = [...originalArray].reverse();
1.27 Array.prototype.shift() - 破壞性
Array.prototype.shift() 是 pop() 的“對(duì)手”。它的核心作用是:從數(shù)組中刪除第一個(gè)元素(索引為 0 的元素),并返回該元素的值。
1.27.1 語(yǔ)法與參數(shù)
const firstElement = arr.shift();
參數(shù):無(wú)。
返回值:
返回從數(shù)組中刪除的那個(gè)元素。
如果數(shù)組是空的,則返回 undefined。
副作用:此方法會(huì)改變?cè)瓟?shù)組,并自動(dòng)更新剩余元素的索引(所有元素向前移動(dòng)一位)。
處理一組按順序到達(dá)的任務(wù),處理完一個(gè)就踢出一個(gè):
const taskQueue = ['download_file', 'extract_zip', 'cleanup'];
while (taskQueue.length > 0) {
const currentTask = taskQueue.shift();
console.log(`正在處理: ${currentTask}`);
}
1.27.2 避坑指南
① 性能警告 (O(n))
這是 shift() 和 pop() 最大的區(qū)別。
pop() 刪除末尾元素,不影響其他元素。
shift() 刪除首位元素后,數(shù)組必須重新排列剩下的每一個(gè)元素以填補(bǔ) 0 號(hào)索引的空缺。
建議:在處理包含數(shù)萬(wàn)個(gè)元素的超大型數(shù)組時(shí),頻繁使用 shift() 會(huì)導(dǎo)致明顯的性能下降。
② 破壞性
- 它會(huì)直接修改原數(shù)組的 length。
1.28 Array.prototype.slice()
它的核心作用是:提取原數(shù)組的一部分,并將其作為一個(gè)新數(shù)組返回。
最關(guān)鍵的一點(diǎn)是:slice() 不會(huì)修改原數(shù)組(非破壞性)。
1.28.1 語(yǔ)法與參數(shù)
const newArray = arr.slice(begin, end);
begin (可選):從該索引開(kāi)始提?。ò撍饕?。
如果是負(fù)數(shù),表示從末尾開(kāi)始算起(例如 -2 表示倒數(shù)第二個(gè))。
如果省略,默認(rèn)為 0。
end (可選):在該索引處結(jié)束提?。ú话撍饕?strong>左閉右開(kāi))。
如果是負(fù)數(shù),表示從末尾開(kāi)始算起(例如 -1 表示提取到倒數(shù)第一個(gè)之前)。
如果省略,默認(rèn)提取到數(shù)組末尾。
返回值:包含提取元素的一個(gè)新數(shù)組。
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant']; console.log(animals.slice(2)); // ["camel", "duck", "elephant"] console.log(animals.slice(2, 4)); // ["camel", "duck"] (不包含索引4) console.log(animals.slice(-2)); // ["duck", "elephant"] (取最后兩個(gè))
淺拷貝整個(gè)數(shù)組
這是在 ES6 展開(kāi)運(yùn)算符 ([…]) 流行之前,克隆數(shù)組最標(biāo)準(zhǔn)的方法:
const original = [1, 2, 3]; const clone = original.slice(); // clone 是一個(gè)新數(shù)組,修改它不會(huì)影響 original
1.28.2 避坑指南
① 淺拷貝陷阱
- slice() 執(zhí)行的是淺拷貝。如果數(shù)組元素是對(duì)象,新數(shù)組和原數(shù)組引用的依然是同一個(gè)對(duì)象內(nèi)存地址。修改對(duì)象內(nèi)部屬性會(huì)兩邊同步。
② 參數(shù)的**“左閉右開(kāi)”**
- 永遠(yuǎn)記?。簊lice(start, end) 包含 start,但不包含 end。
1.29 Array.prototype.some()
它的核心作用是:測(cè)試數(shù)組中是否至少有一個(gè)元素通過(guò)了由提供的函數(shù)實(shí)現(xiàn)的測(cè)試。
它返回一個(gè) 布爾值,且具有 “短路”特性。
1.29.1 語(yǔ)法與參數(shù)
const hasMatch = arr.some(callbackFn(element, index, array), thisArg);
callbackFn (測(cè)試函數(shù)):為每個(gè)元素執(zhí)行的函數(shù)。只要該函數(shù)對(duì)任意一個(gè)元素返回 true(真值),some() 就會(huì)立即停止遍歷并返回 true。
返回值:布爾值 (true / false)。
邏輯等價(jià):它相當(dāng)于邏輯運(yùn)算中的 “或”
檢查用戶組里是否有管理員:
const users = [
{ name: 'Tom', role: 'user' },
{ name: 'Jerry', role: 'admin' },
{ name: 'Spike', role: 'user' }
];
const hasAdmin = users.some(user => user.role === 'admin');
// true (在遍歷到 Jerry 時(shí)就停止了)
替代 includes 查找復(fù)雜對(duì)象
includes() 只能找簡(jiǎn)單值或引用地址,而 some() 可以根據(jù)屬性查找:
const fruits = [{ id: 1, name: 'apple' }, { id: 2, name: 'banana' }];
const hasApple = fruits.some(f => f.name === 'apple'); // true
1.29.2 避坑指南
① 空數(shù)組陷阱
- 對(duì)于空數(shù)組,some() 永遠(yuǎn)返回 false。因?yàn)闆](méi)有任何元素能通過(guò)測(cè)試。
② 短路機(jī)制 (Short-circuiting)
- some() 一旦碰到返回 true 的回調(diào),剩下的元素就不會(huì)再被處理了。如果你在回調(diào)里寫(xiě)了副作用操作(如打印日志),你會(huì)發(fā)現(xiàn)后面的日志沒(méi)出來(lái)。
③ 非破壞性
- 它不會(huì)修改原數(shù)組。
1.30 Array.prototype.sort() - 破壞性
對(duì)數(shù)組元素進(jìn)行原地(In-place)排序
1.30.1 語(yǔ)法與參數(shù)
arr.sort(compareFn);
compareFn (可選):定義排序順序的函數(shù)。如果省略,數(shù)組元素將按照轉(zhuǎn)換為字符串后的 Unicode 位點(diǎn)(Code points)進(jìn)行排序。
返回值:指向原數(shù)組的引用(排序后的數(shù)組)。
副作用:破壞性方法。它會(huì)直接修改原數(shù)組。
核心痛點(diǎn):為什么 [10, 2].sort() 會(huì)變成 [10, 2]?
這是新手最常遇到的坑。默認(rèn)情況下,sort() 會(huì)把元素當(dāng)成字符串處理:
“10” 的第一個(gè)字符是 “1”。
“2” 的第一個(gè)字符是 “2”。
因?yàn)?“1” 的字符編碼比 “2” 小,所以 10 排在 2 前面。
引入意義: 為了正確排序數(shù)字或自定義對(duì)象,你必須提供一個(gè)比較函數(shù) compareFn。
比較函數(shù) compareFn(a, b) 的邏輯
該函數(shù)應(yīng)返回一個(gè)數(shù)字,告訴引擎如何交換位置:
小于 0:a 排在 b 前面。
等于 0:保持相對(duì)位置不變。
大于 0:b 排在 a 前面。
const numbers = [10, 5, 8, 1, 7]; // 升序排列 numbers.sort((a, b) => a - b); // [1, 5, 7, 8, 10] // 降序排列 numbers.sort((a, b) => b - a); // [10, 8, 7, 5, 1]
1.30.2 避坑指南
① 破壞性
- 由于它直接修改原數(shù)組,在 React 等環(huán)境中,建議先拷貝再排序:
const sorted = [...originalArray].sort();
② 穩(wěn)定性 (Stability)
- 從 ES2019 開(kāi)始,JavaScript 規(guī)范要求 sort() 必須是穩(wěn)定排序。這意味著如果兩個(gè)元素相等,它們?cè)谂判蚝蟮南鄬?duì)順序必須與排序前一致。
1.31 Array.prototype.splice() - 破壞性
它的核心作用是:在數(shù)組的 任意位置 進(jìn)行 刪除、替換或添加元素。
1.31.1 語(yǔ)法與參數(shù)
const deletedItems = arr.splice(start, deleteCount, item1, item2, ...);
- start (必填):指定修改的開(kāi)始位置(索引)。
- 如果是負(fù)數(shù),則從數(shù)組末尾開(kāi)始計(jì)算。
- deleteCount (可選):整數(shù),表示要移除的數(shù)組元素的個(gè)數(shù)。
- 如果設(shè)置為 0,則不刪除元素(通常用于純插入)。
- item1, item2, … (可選):要添加進(jìn)數(shù)組的元素,從 start 位置開(kāi)始。
- 返回值:一個(gè)包含被刪除元素的新數(shù)組。如果沒(méi)有刪除任何元素,則返回空數(shù)組 []。
A. 刪除元素
從索引 2 開(kāi)始刪除 1 個(gè)元素:
const fruits = ['apple', 'banana', 'orange', 'mango']; fruits.splice(2, 1); // fruits 變?yōu)? ['apple', 'banana', 'mango']
B. 插入元素
在索引 2 的位置插入 ‘lemon’,不刪除任何東西:
const fruits = ['apple', 'banana', 'mango']; fruits.splice(2, 0, 'lemon'); // fruits 變?yōu)? ['apple', 'banana', 'lemon', 'mango']
C. 替換元素
刪除 1 個(gè)并原地填補(bǔ) 1 個(gè):
const fruits = ['apple', 'banana', 'mango']; fruits.splice(1, 1, 'strawberry'); // fruits 變?yōu)? ['apple', 'strawberry', 'mango']
1.31.2 避坑指南
分不清 splice 和 slice?
Splice 中的 P 可以記作 Permanent(永久的)或 Patch(打補(bǔ)?。?,因?yàn)樗鼤?huì)永久修改原數(shù)組。
Slice 可以記作 Share(分享),它只是切一塊出來(lái)分享給你,原件不動(dòng)。
性能開(kāi)銷:由于 splice 涉及到刪除和插入,在數(shù)組中間操作會(huì)導(dǎo)致后續(xù)所有元素重排索引,在處理超大型數(shù)組時(shí),性能開(kāi)銷比 pop 或 push 大。
負(fù)數(shù)索引:如果你寫(xiě) arr.splice(-1, 1),它會(huì)非常方便地刪掉數(shù)組的最后一個(gè)元素。
1.32 Array.prototype.toLocaleString()
它的核心作用是:將數(shù)組中的每個(gè)元素根據(jù)特定的語(yǔ)言環(huán)境(如時(shí)區(qū)、貨幣格式、數(shù)字分隔符)轉(zhuǎn)換成字符串,并用逗號(hào)連接。
1.32.1 語(yǔ)法與參數(shù)
const str = arr.toLocaleString(locales, options);
locales (可選):一個(gè)帶有 BCP 47 語(yǔ)言標(biāo)簽的字符串(如 ‘zh-CN’、‘en-US’)。
options (可選):一個(gè)配置對(duì)象,用于定義數(shù)字、日期或貨幣的具體格式。
返回值:根據(jù)本地習(xí)慣格式化后的字符串。
為什么要使用它?
普通的 toString() 或 join() 只是機(jī)械地把值轉(zhuǎn)成字符串。但在處理金錢(qián)、日期或大數(shù)字時(shí),不同國(guó)家有不同的寫(xiě)法。
- 引入意義:它讓前端開(kāi)發(fā)者無(wú)需手動(dòng)編寫(xiě)復(fù)雜的正則或邏輯,就能輕松實(shí)現(xiàn)國(guó)際化(i18n)。
貨幣轉(zhuǎn)換
這是它最強(qiáng)大的地方之一,可以配合 options 自動(dòng)添加貨幣符號(hào):
const prices = [100.5, 200, 3000];
const formatted = prices.toLocaleString('zh-CN', {
style: 'currency',
currency: 'CNY'
});
// "¥100.50,¥200.00,¥3,000.00"
日期數(shù)組本地化
const dates = [new Date(), new Date('2026-01-01')];
console.log(dates.toLocaleString('zh-CN'));
// "2026/2/27 13:56:43, 2026/1/1 08:00:00"
1.33 Array.prototype.toReversed()
Array.prototype.toReversed() 是 ES2023 (ES14) 引入的新特性。它的核心作用是:返回一個(gè)元素順序顛倒的新數(shù)組,而 保持原數(shù)組不變。
1.33.1 語(yǔ)法與參數(shù)
const reversedArray = arr.toReversed();
參數(shù):無(wú)。
返回值:一個(gè)新的數(shù)組,其元素順序與原數(shù)組相反。
對(duì)原數(shù)組的影響:無(wú)(它是非破壞性的)。
const original = [1, 2, 3]; const reversed = original.toReversed(); console.log(original); // [1, 2, 3] <- 穩(wěn)如泰山 console.log(reversed); // [3, 2, 1] <- 得到想要的結(jié)果
1.33.2 避坑指南
淺拷貝:和 slice() 一樣,toReversed() 執(zhí)行的是淺拷貝。如果數(shù)組里存的是對(duì)象,新舊數(shù)組引用的依然是同一個(gè)對(duì)象。
處理稀疏數(shù)組:toReversed() 在處理空洞(holes)時(shí),會(huì)將空洞轉(zhuǎn)換為 undefined,而傳統(tǒng)的 reverse() 會(huì)保留空洞。
1.34 Array.prototype.toSorted()
它是經(jīng)典 sort() 方法的“純函數(shù)”版本,其核心作用是:返回一個(gè)排序后的新數(shù)組,而完全不修改原始數(shù)組。
1.34.1 語(yǔ)法與參數(shù)
const sortedArray = arr.toSorted(compareFn);
compareFn (可選):與 sort() 的比較函數(shù)完全一致。如果省略,依然會(huì)默認(rèn)按字符串 Unicode 位點(diǎn)排序。
返回值:一個(gè)新的數(shù)組,其中的元素已按指定順序排列。
對(duì)原數(shù)組的影響:無(wú)(非破壞性)。
const numbers = [10, 5, 8]; // 錯(cuò)誤寫(xiě)法:const s = numbers.sort(); 這會(huì)改掉 numbers const sorted = [...numbers].sort((a, b) => a - b);
const numbers = [10, 5, 8]; const sorted = numbers.toSorted((a, b) => a - b); console.log(numbers); // [10, 5, 8] (原封不動(dòng)) console.log(sorted); // [5, 8, 10] (得到新數(shù)組)
1.34.2 避坑指南
① 依然需要比較函數(shù)
- 它并沒(méi)有解決 [10, 2].sort() 變成 [10, 2] 的邏輯問(wèn)題。對(duì)于數(shù)字?jǐn)?shù)組,你依然需要傳入 (a, b) => a - b。
② 處理稀疏數(shù)組
- 這是它與 sort() 的細(xì)微差別:toSorted() 會(huì)將數(shù)組中的空洞(holes)轉(zhuǎn)換為 undefined,并像對(duì)待普通元素一樣進(jìn)行排序(通常排在最后)。
1.35 Array.prototype.toSpliced()
它是經(jīng)典 splice() 的“克隆版”,核心作用是:返回一個(gè)執(zhí)行了刪除、替換或插入操作后的新數(shù)組,而保持原數(shù)組完全不變。
1.35.1 語(yǔ)法與參數(shù)
const newArray = arr.toSpliced(start, deleteCount, item1, item2, ...);
參數(shù):與 splice() 完全一致。
start:開(kāi)始索引。
deleteCount:刪除的元素個(gè)數(shù)。
item1…:要插入的新元素。
返回值:修改后的完整新數(shù)組。
對(duì)原數(shù)組的影響:無(wú)(非破壞性)。
const months = ["Jan", "Mar", "Apr"]; const fullMonths = months.toSpliced(1, 0, "Feb"); console.log(months); // ["Jan", "Mar", "Apr"] (原封不動(dòng)) console.log(fullMonths); // ["Jan", "Feb", "Mar", "Apr"]
const numbers = [10, 20, 30, 40]; const result = numbers .toSpliced(1, 1, 25) // 把 20 換成 25 .map(n => n * 2); // [20, 50, 60, 80]
1.35.2 避坑指南
- 返回值差異(重點(diǎn)):splice() → \rightarrow → 返回 [被刪除的元素]。toSpliced() → \rightarrow → 返回 [修改后的全量新數(shù)組]。
- 淺拷貝:與其它“to”系列方法一樣,它執(zhí)行的是淺拷貝。如果數(shù)組內(nèi)是對(duì)象,引用關(guān)系依然存在。
1.36 Array.prototype.toString()
Array.prototype.toString() 是 JavaScript 數(shù)組最基礎(chǔ)的類型轉(zhuǎn)換方法。它的核心作用是:將數(shù)組中的所有元素轉(zhuǎn)換成字符串,并用 逗號(hào) 連接成一個(gè)長(zhǎng)字符串。
1.36.1 語(yǔ)法與參數(shù)
const resultString = arr.toString();
參數(shù):無(wú)。
返回值:一個(gè)表示數(shù)組所有元素的字符串。
副作用:非破壞性。它不會(huì)改變?cè)瓟?shù)組。
const arr = [1, 2, 'a', 'b']; console.log(arr.toString()); // "1,2,a,b" const dateArr = [new Date(2026, 0, 1)]; console.log(dateArr.toString()); // "Thu Jan 01 2026 00:00:00 GMT..."
1.36.2 避坑指南
A. 嵌套數(shù)組會(huì)被“拍平”
- 這是 toString() 一個(gè)比較獨(dú)特的特性(有時(shí)也是坑)。它會(huì)遞歸地調(diào)用嵌套數(shù)組的 toString,導(dǎo)致多維數(shù)組看起來(lái)像一維數(shù)組的字符串:
const nested = [1, [2, 3], [4, [5]]]; console.log(nested.toString()); // "1,2,3,4,5"
- 如果你需要保留數(shù)組結(jié)構(gòu)(如 JSON 格式),請(qǐng)使用 JSON.stringify(arr)。
B. null 和 undefined 的特殊處理
- 在數(shù)組中,null 和 undefined 會(huì)被轉(zhuǎn)換為空字符串:
const arr = [1, null, 3, undefined]; console.log(arr.toString()); // "1,,3,"
自動(dòng)類型轉(zhuǎn)換
- 在 JavaScript 的隱式轉(zhuǎn)換中,toString() 經(jīng)常在幕后工作。例如,當(dāng)數(shù)組與字符串相加時(shí):
const arr = [1, 2, 3];
console.log("Result: " + arr); // "Result: 1,2,3"
// 實(shí)際上發(fā)生了: "Result: " + arr.toString()
1.37 Array.prototype.unshift() - 破壞性
Array.prototype.unshift() 是 push() 的“鏡像”方法。它的核心作用是:將一個(gè)或多個(gè)元素添加到數(shù)組的開(kāi)頭。
1.37.1 語(yǔ)法與參數(shù)
const newLength = arr.unshift(element1, element2, ..., elementN);
參數(shù):想要添加到數(shù)組開(kāi)頭的元素。
返回值:添加新元素后數(shù)組的最新長(zhǎng)度 (length)。
副作用:此方法會(huì)改變?cè)瓟?shù)組(原地修改)。
const numbers = [3, 4]; numbers.unshift(1, 2); // [1, 2, 3, 4]
1.37.2 避坑指南
① 返回值是長(zhǎng)度
- 和 push 一樣,它返回的是數(shù)組的新長(zhǎng)度,而不是修改后的數(shù)組本身。
const result = [2, 3].unshift(1); console.log(result); // 3 (數(shù)組長(zhǎng)度)
② 破壞性
- 它會(huì)直接修改你的原始變量。在 React 等需要“不可變數(shù)據(jù)”的場(chǎng)景,建議使用展開(kāi)運(yùn)算符:
const newArr = [newItem, ...oldArr];
1.38 Array.prototype.values()
它的核心作用是:返回一個(gè)新的數(shù)組迭代器(Array Iterator)對(duì)象,該對(duì)象包含了數(shù)組中每個(gè)索引對(duì)應(yīng)的值。
1.38.1 語(yǔ)法與參數(shù)
const iterator = arr.values();
參數(shù):無(wú)。
返回值:一個(gè)新的 Array Iterator 對(duì)象。
特性:它不存儲(chǔ)實(shí)際的值,而是提供了一種按序訪問(wèn)原數(shù)組值的方式。
A. 配合 for…of 循環(huán)
這是最自然的使用方式(盡管直接遍歷數(shù)組更常見(jiàn),但 values() 讓語(yǔ)義更顯式):
const fruits = ['apple', 'banana', 'cherry'];
const iterator = fruits.values();
for (const value of iterator) {
console.log(value);
}
// 輸出: apple, banana, cherry
B. 手動(dòng)控制遍歷進(jìn)度
你可以通過(guò)調(diào)用 .next() 逐步獲取值,這在實(shí)現(xiàn)復(fù)雜的異步邏輯或生成器時(shí)非常有用:
const arr = ['a', 'b'];
const iter = arr.values();
console.log(iter.next()); // { value: 'a', done: false }
console.log(iter.next()); // { value: 'b', done: false }
console.log(iter.next()); // { value: undefined, done: true }
1.39 Array.prototype.with()
它的核心作用是:修改數(shù)組中指定索引的值,并返回一個(gè)新數(shù)組,而不改變?cè)瓟?shù)組。
1.39.1 語(yǔ)法與參數(shù)
const newArray = arr.with(index, value);
index:要修改的索引(支持負(fù)數(shù),-1 代表最后一個(gè)元素)。
value:要放入該位置的新值。
返回值:一個(gè)新的數(shù)組,其中指定索引處已被替換為新值。
對(duì)原數(shù)組的影響:無(wú)(非破壞性)。
const arr = [1, 2, 3]; // 舊方案 1:展開(kāi)運(yùn)算符 const newArr = [...arr]; newArr[1] = 99; // 舊方案 2:slice const newArr2 = arr.slice(0, 1).concat(99, arr.slice(2));
const temperatures = [22, 25, 21, 28]; const corrected = temperatures.with(2, 23); console.log(temperatures); // [22, 25, 21, 28] (原封不動(dòng)) console.log(corrected); // [22, 25, 23, 28] (索引 2 已更新)
const players = ['Alice', 'Bob', 'Charlie']; const updated = players.with(-1, 'Zoe'); // ['Alice', 'Bob', 'Zoe']
1.39.2 避坑指南
超出索引范圍:如果索引超出了數(shù)組范圍(無(wú)論是正向還是負(fù)向),with() 會(huì)拋出 RangeError。
淺拷貝:與 toSorted 或 toReversed 一樣,它執(zhí)行的是淺拷貝。如果替換的是對(duì)象,雖然新數(shù)組指向了新引用,但未被替換的其他對(duì)象元素依然引用著同一份內(nèi)存地址。
二、 Array 靜態(tài)方法 (Static Methods)
2.1 Array.from()
將 類數(shù)組對(duì)象(Array-like)或 可迭代對(duì)象(Iterable)轉(zhuǎn)換成一個(gè)真正的數(shù)組。
它是一個(gè)靜態(tài)方法,必須通過(guò) Array.from() 調(diào)用,而不是在數(shù)組實(shí)例上調(diào)用。
2.1.1 語(yǔ)法與參數(shù)
Array.from(arrayLike, mapFn, thisArg);
arrayLike (必填):想要轉(zhuǎn)換的對(duì)象。
- 類數(shù)組:擁有 length 屬性和索引元素的對(duì)象(如 arguments 或 NodeList)。
- 可迭代對(duì)象:實(shí)現(xiàn)了迭代協(xié)議的對(duì)象(如 Set、Map 或 String)。
mapFn (可選):新數(shù)組中的每個(gè)元素都會(huì)執(zhí)行的回調(diào)函數(shù),類似于 .map()。
返回值:一個(gè)新的數(shù)組實(shí)例。
A. 將 Set 或 Map 轉(zhuǎn)為數(shù)組
常用于數(shù)組去重:
const set = new Set([1, 2, 2, 3]); const uniqueArr = Array.from(set); // [1, 2, 3]
B. 操作 DOM NodeList
讓 querySelectorAll 獲取的節(jié)點(diǎn)可以使用數(shù)組方法:
const divs = document.querySelectorAll('div');
const divIds = Array.from(divs, div => div.id);
C. 快速生成序列
這是 Array.from() 最精妙的用法之一,可以替代繁瑣的 for 循環(huán):
// 生成 0 到 4 的數(shù)組
const range = Array.from({ length: 5 }, (v, i) => i);
// [0, 1, 2, 3, 4]
2.1.2 避坑指南
① 淺拷貝
- Array.from() 創(chuàng)建的是原始數(shù)據(jù)的淺拷貝。如果轉(zhuǎn)換的對(duì)象內(nèi)部包含引用類型,新數(shù)組和原對(duì)象共享這些引用。
② 與展開(kāi)運(yùn)算符 ([…]) 的區(qū)別
[…] 只能轉(zhuǎn)換可迭代對(duì)象(Iterable)。
Array.from() 還能轉(zhuǎn)換類數(shù)組對(duì)象(只需有 length 屬性即可)。
// 只有 Array.from 能處理這個(gè):
const obj = { length: 2, 0: 'a', 1: 'b' };
console.log(Array.from(obj)); // ['a', 'b']
console.log([...obj]); // TypeError: obj is not iterable
2.2 Array.fromAsync()
它是 Array.from() 的異步孿生兄弟,專門(mén)用于處理 異步可迭代對(duì)象(Async Iterables),例如從網(wǎng)絡(luò)流、數(shù)據(jù)庫(kù)游標(biāo)或異步生成器中獲取數(shù)據(jù)。
2.2.1 語(yǔ)法與參數(shù)
const newArray = await Array.fromAsync(asyncIterable, mapFn, thisArg);
asyncIterable:一個(gè)異步可迭代對(duì)象(如 ReadableStream)、同步可迭代對(duì)象(如 Array、Set)或類數(shù)組對(duì)象。
mapFn (可選):對(duì)每個(gè)元素執(zhí)行的函數(shù)。這個(gè)函數(shù)可以是異步的(返回 Promise),fromAsync 會(huì)等待它解析。
返回值:一個(gè) Promise,解析后得到一個(gè)新的數(shù)組實(shí)例。
為什么要使用它?
在它出現(xiàn)之前,如果你想把一個(gè)異步迭代器轉(zhuǎn)換為數(shù)組,你需要使用 for await…of 循環(huán):
const arr = [];
for await (const item of asyncGen()) {
arr.push(item);
}
A. 轉(zhuǎn)換異步生成器 (Async Generator)
async function* asyncGen() {
yield Promise.resolve(1);
yield 2;
yield 3;
}
const arr = await Array.fromAsync(asyncGen());
console.log(arr); // [1, 2, 3]
2.3 Array.isArray()
Array.isArray() 是判斷一個(gè)變量是否為數(shù)組的終極權(quán)威方法。它的核心作用是:可靠地檢測(cè)傳入的值是否是一個(gè)真正的 Array 實(shí)例。
2.3.1 語(yǔ)法與參數(shù)
const result = Array.isArray(value);
- 返回值:如果是數(shù)組則返回 true,否則返回 false(即使是類數(shù)組對(duì)象或 null 也會(huì)返回 false)。
為什么不用 typeof?
在 JavaScript 的歷史中,檢測(cè)數(shù)組一直是個(gè)麻煩事:
typeof 的局限:typeof [] 會(huì)返回 “object”。這讓你無(wú)法區(qū)分它是普通對(duì)象、數(shù)組還是 null。
instanceof 的跨環(huán)境陷阱:在網(wǎng)頁(yè)開(kāi)發(fā)中,如果你有多個(gè) iframe,每個(gè) iframe 都有自己的全局環(huán)境(和自己的 Array 構(gòu)造函數(shù))。從一個(gè) iframe 傳到另一個(gè) iframe 的數(shù)組,在主頁(yè)面的 instanceof Array 檢測(cè)中會(huì)失效。
引入意義: Array.isArray() 能夠跨越 iframe 或不同的執(zhí)行上下文,始終準(zhǔn)確地識(shí)別數(shù)組。
// 全部為 true
Array.isArray([]);
Array.isArray([1, 2]);
Array.isArray(new Array());
Array.isArray(Array.prototype); // 沒(méi)錯(cuò),原型也是數(shù)組
// 全部為 false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(17);
Array.isArray('Array');
Array.isArray(new Uint8Array(10)); // 類型化數(shù)組不是普通數(shù)組
2.4 Array.of()
創(chuàng)建一個(gè)具有可變數(shù)量參數(shù)的新數(shù)組實(shí)例,而不考慮參數(shù)的數(shù)量或類型。
2.4.1 語(yǔ)法與參數(shù)
Array.of(element0, element1, ..., elementN);
參數(shù):任意數(shù)量的元素,這些元素將按順序成為新數(shù)組的成員。
返回值:一個(gè)新的 Array 實(shí)例。
為什么要使用它?(解決 Array 構(gòu)造函數(shù)的陷阱)
這是 Array.of() 存在的唯一且最重要的原因。傳統(tǒng)的 Array() 構(gòu)造函數(shù)在處理單個(gè)數(shù)字參數(shù)時(shí)存在一個(gè)非常迷惑的行為:
new Array(7):創(chuàng)建一個(gè)長(zhǎng)度為 7 的空數(shù)組(只有空位,沒(méi)有元素)。
Array.of(7):創(chuàng)建一個(gè)包含單個(gè)元素 7 的數(shù)組 [7]。
引入意義:它提供了一個(gè)行為始終統(tǒng)一的數(shù)組創(chuàng)建方式,無(wú)論你傳入的是什么、傳入了多少個(gè)。
A. 修正構(gòu)造函數(shù)歧義
當(dāng)你需要?jiǎng)討B(tài)創(chuàng)建一個(gè)包含單個(gè)數(shù)字的數(shù)組時(shí),Array.of() 是最安全的選擇:
const size = 7; const a = new Array(size); // [empty × 7] const b = Array.of(size); // [7]
2.4.2 避坑指南
與 Array.from() 的區(qū)別:
Array.from() 是把“像數(shù)組的東西”轉(zhuǎn)換成數(shù)組。
Array.of() 是把“零散的參數(shù)”組合成數(shù)組。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript中URL.createObjectURL和Blob實(shí)現(xiàn)保存文件
本文介紹了利用JavaScript中的Blob對(duì)象和URL.createObjectURL方法在瀏覽器端創(chuàng)建文件并實(shí)現(xiàn)下載功能,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-07-07
JS首屏加載時(shí)間優(yōu)化的解決方法總結(jié)
首屏加載時(shí)間是一個(gè)衡量網(wǎng)頁(yè)性能和用戶體驗(yàn)的關(guān)鍵指標(biāo),這個(gè)問(wèn)題無(wú)論是在面試中還是在項(xiàng)目開(kāi)發(fā)中都占有極其高的權(quán)重,本文為大家整理了幾種JS中優(yōu)化首屏加載時(shí)間的方法,希望對(duì)大家有所幫助2024-02-02
整理Javascript數(shù)組學(xué)習(xí)筆記
整理Javascript數(shù)組學(xué)習(xí)筆記,之前一系列的文章是跟我學(xué)習(xí)Javascript,本文就是進(jìn)一步學(xué)習(xí)javascript數(shù)組,希望大家繼續(xù)關(guān)注2015-11-11
JavaScript折半查找(二分查找)算法原理與實(shí)現(xiàn)方法示例
這篇文章主要介紹了JavaScript折半查找(二分查找)算法原理與實(shí)現(xiàn)方法,結(jié)合具體問(wèn)題描述了折半查找算法的原理、實(shí)現(xiàn)方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2018-08-08
javascript實(shí)現(xiàn)數(shù)字時(shí)鐘效果
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)數(shù)字時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02
JavaScript 創(chuàng)建隨機(jī)數(shù)和隨機(jī)圖片
關(guān)于javascript隨機(jī)數(shù)的,很早以前的文章了,不過(guò)內(nèi)容還是不錯(cuò)的,如果想要更多的效果,可以去腳本之家搜下。2009-12-12

