Hai method có tên gần giống nhau nhưng argument thứ hai và tác động lên dữ liệu khác nhau. Đọc nhầm slice(1, 2) thành “lấy hai phần tử” hoặc coi kết quả splice là mảng sau chỉnh sửa sẽ tạo lỗi dù code không ném exception.
Bài so sánh theo cùng tiêu chí: hợp đồng arguments, kết quả trả về, mutation, reference và chi phí tích hợp. Snippet đã chạy bằng Node.js 24.18.1, tài liệu MDN được đọc ngày 04/11/2026. Không có benchmark tốc độ hoặc bộ nhớ.
Chạy hai thao tác trên cùng dữ liệu đầu
Lưu thành arrays.cjs, chạy node arrays.cjs:
const assert = require('node:assert/strict');
const original = ['a', 'b', 'c', 'd'];
const selected = original.slice(1, 2);
assert.deepEqual(selected, ['b']);
assert.deepEqual(original, ['a', 'b', 'c', 'd']);
assert.notEqual(selected, original);
const editable = ['a', 'b', 'c', 'd'];
const removed = editable.splice(1, 2, 'x');
assert.deepEqual(removed, ['b', 'c']);
assert.deepEqual(editable, ['a', 'x', 'd']);
console.log(selected, removed, editable);
Các assertion đã qua. slice lấy từ index 1 đến trước index 2, nên chỉ lấy b. splice bắt đầu ở index 1 và xóa hai phần tử, rồi chèn x tại đó. Array trả về từ splice chứa phần bị lấy ra, trong khi editable mới là mảng đã chỉnh sửa.
Về khả năng bắt đầu và hệ sinh thái, cả hai đều có sẵn trong JavaScript, không cần package. Sự khác biệt cần ưu tiên ở đây là dữ liệu sau thao tác có đúng yêu cầu hay không; độ ngắn tên hàm không phải tiêu chí lựa chọn.
Một đối chiếu bằng lời để review
Với slice, argument thứ hai là mốc kết thúc không bao gồm vị trí đó. Nó phù hợp khi muốn một đoạn dữ liệu mới và giữ cấu trúc mảng gốc. Với splice, argument thứ hai là số phần tử xóa; các arguments tiếp theo là phần tử chèn vào. Nó phù hợp khi chủ ý chỉnh sửa mảng đang sở hữu.
Nếu cần cập nhật state theo cách tạo mảng mới, không gọi splice trực tiếp lên array state rồi chỉ truyền lại cùng reference. Nếu muốn dùng splice trên một bản sao do mình tạo, hãy làm rõ bước sao chép và giới hạn nông của bản sao ấy. Không phải mọi mutation đều sai, nhưng ownership phải dễ nhìn thấy.
Sao chép mảng không đồng nghĩa sao chép object con
Chạy snippet độc lập sau:
const assert = require('node:assert/strict');
const rows = [{id: 1, title: 'Draft'}, {id: 2, title: 'Ready'}];
const selected = rows.slice(0, 1);
assert.notEqual(selected, rows);
assert.equal(selected[0], rows[0]);
selected[0].title = 'Edited';
assert.equal(rows[0].title, 'Edited');
console.log(rows[0].title);
Kết quả đã kiểm tra là Edited. Array mới có danh tính riêng nhưng phần tử object vẫn cùng reference. Ví dụ này chỉ kiểm chứng plain object trong mảng đặc; nó không giới thiệu một giải pháp deep clone cho mọi kiểu dữ liệu.
Trong bài toán lấy một đoạn để hiển thị, có thể bạn không cần đổi object con. Nếu sau đó chỉnh nội dung, hãy quyết định bản cập nhật phải ảnh hưởng dữ liệu gốc hay tạo phiên bản mới, thay vì suy rằng slice đã cô lập mọi thứ.
Kiểm tra những biên dễ đọc nhầm
Thử khoảng rỗng, index cuối và các giá trị âm theo tài liệu trước khi đưa helper vào xử lý pagination. Đặt tên biến như endExclusive hoặc deleteCount giúp người gọi ít nhầm hơn một tên chung second.
Khi review kết quả splice, kiểm tra cả array trả về và array đầu vào sau thao tác. Chỉ assert phần bị xóa sẽ bỏ sót lỗi chèn nhầm vị trí. Với slice, kiểm tra mảng nguồn giữ nguyên và phần được chọn đúng khoảng.
Hai API không phải hai biến thể có thể thay nhau tùy ý. Chọn theo phép biến đổi cần thực hiện, rồi xác nhận mutation và reference đúng với nơi dữ liệu sẽ được dùng tiếp. Chưa có bằng chứng hiệu năng trong bài để xếp một cách luôn tốt hơn cách còn lại.


