JavaScript splice 回傳空陣列?分清刪除結果與原陣列
items.splice(1, 0, item) 已把資料插入陣列,接住的結果卻是 []。splice 會修改原陣列,回傳值則是被刪除元素組成的陣列;刪除數量為零時,空回傳值就是預期結果。 要拿修改後的內容,繼續使用原陣列;要保留原陣列並取得編輯後副本,可選 toSpliced()。
同時檢查回傳值與原陣列
下面兩個 JavaScript 區塊可分別存成 .mjs,使用 Node.js 執行。MDN splice的第二個參數是刪除數量;slice 的第二個參數則是結束索引,且不包含該位置。
import assert from 'node:assert/strict';
const items = ['A', 'C'];const removed = items.splice(1, 0, 'B');assert.deepEqual(removed, []);assert.deepEqual(items, ['A', 'B', 'C']);assert.deepEqual(items.splice(1, 1, 'X'), ['B']);assert.deepEqual(items, ['A', 'X', 'C']);assert.deepEqual(items.slice(1, 2), ['X']);assert.deepEqual(items, ['A', 'X', 'C']);
const omitted = ['A', 'B', 'C'];assert.deepEqual(omitted.splice(1), ['B', 'C']);const explicit = ['A', 'B', 'C'];assert.deepEqual(explicit.splice(1, undefined), []);assert.deepEqual(explicit, ['A', 'B', 'C']);
const original = [{ id: 'A' }, { id: 'B' }];const edited = original.toSpliced(1, 1);assert.equal(original.length, 2);assert.equal(edited.length, 1);assert.equal(edited[0], original[0]); // 保留元素的物件仍共用參照console.log('splice return and mutation: PASS');省略 deleteCount 會從起點刪到最後;明確傳 undefined 則轉成零。因此將可選欄位直接塞進 splice(start, options.deleteCount),和只傳 splice(start) 可能有不同結果。包裝函式應先決定預設語意,再組合參數。
toSpliced回傳編輯後的新陣列,與 splice 的回傳契約不同。它保留的物件元素仍是同一份參照;若接著修改 edited[0].id,原陣列對應物件也會變。需要隔離物件內容時,再評估 structuredClone 的支援型別與限制。
依 ID 刪除前,先接住 findIndex 的 -1
清單沒有該 ID 時,findIndex 回傳 -1。直接交給 splice(-1, 1) 會刪掉最後一筆,這比空回傳值更容易傷到資料。
這個 helper 限定普通、無空槽且 ID 唯一的資料陣列,回傳新的清單與是否找到。找不到時保留原參照,讓呼叫端明確顯示「資料已不存在」。
import assert from 'node:assert/strict';
function removeFirstById(items, id) { const index = items.findIndex(item => item.id === id); if (index === -1) return { found: false, items }; return { found: true, items: items.toSpliced(index, 1) };}
const original = [{ id: 'A' }, { id: 'B' }, { id: 'C' }];const missing = removeFirstById(original, 'missing');assert.equal(missing.found, false);assert.equal(missing.items, original);assert.deepEqual(original.map(item => item.id), ['A', 'B', 'C']);const result = removeFirstById(original, 'B');assert.equal(result.found, true);assert.deepEqual(result.items.map(item => item.id), ['A', 'C']);assert.notEqual(result.items, original);assert.equal(result.items[0], original[0]);assert.equal(original.length, 3);assert.equal(removeFirstById([], 'A').found, false);console.log('missing ID preserves data: PASS');函式名稱中的 First 也交代只刪除第一筆符合項目。若資料可能有重複 ID,應先在入口決定重複資料的處理規則,可參考 Set 與依 ID 去重的差異。
2026-11-04 維護流程在 macOS、Node.js v24.13.0 執行上述兩個程式,斷言通過。部署到較舊環境前,先確認 typeof Array.prototype.toSpliced === 'function';缺少時,可在確認 index 非負後,用 items.slice(0, index).concat(items.slice(index + 1)) 組合副本。本文未測試框架的畫面更新機制。
參考資料: