Lập trình · 23/10/2026

JavaScript reverse và toReversed: đảo thứ tự có sửa mảng gốc không?

const reversed = rows.reverse() không tạo ra một mảng độc lập. Mảng rows đã bị đảo tại chỗ, còn reversed trỏ tới chính mảng đó. Nếu nhiều thành phần cùng dùng dữ liệu nguồn, một lần đảo để hiển thị có thể làm thứ tự ở nơi khác thay đổi.

JavaScript reverse và toReversed: đảo thứ tự có sửa mảng gốc không?

const reversed = rows.reverse() không tạo ra một mảng độc lập. Mảng rows đã bị đảo tại chỗ, còn reversed trỏ tới chính mảng đó. Nếu nhiều thành phần cùng dùng dữ liệu nguồn, một lần đảo để hiển thị có thể làm thứ tự ở nơi khác thay đổi.

1. reverse sửa nguồn và trả cùng tham chiếu

const rows = ['A', 'B', 'C'];
const alias = rows;
const reversed = rows.reverse();
console.log(JSON.stringify(rows)); // ["C","B","A"]
console.log(reversed === rows); // true
console.log(JSON.stringify(alias)); // ["C","B","A"]

MDN Array.reverse mô tả thao tác đảo tại chỗ và trả lại chính mảng. Tạo tên biến mới không thay đổi đặc tính đó. const chỉ ngăn gán lại biến, không cấm sửa các phần tử của mảng.

Nếu một hàm render gọi reverse trên dữ liệu dùng chung, lần gọi sau có thể đảo ngược lại thứ tự vừa nhận. Chọn rõ quyền sở hữu dữ liệu: nơi nào được phép sửa nguồn, nơi nào chỉ được tạo thứ tự hiển thị riêng.

2. toReversed tạo mảng ngoài mới nhưng không sao chép sâu

const first = { id: 'A', count: 1 };
const rows = [first, { id: 'B', count: 2 }];
const reversed = rows.toReversed();
console.log(rows.map(row => row.id).join(',')); // A,B
console.log(reversed.map(row => row.id).join(',')); // B,A
console.log(reversed === rows); // false
reversed[1].count = 7;
console.log(rows[0].count); // 7

toReversed trả mảng mới theo thứ tự đảo, giữ nguyên thứ tự mảng nguồn. Tuy vậy, object phần tử vẫn dùng chung tham chiếu. Sửa count qua reversed vì thế vẫn xuất hiện trong rows.

Phân biệt độc lập về thứ tự với độc lập về nội dung bản ghi. Nếu sản phẩm cần bản nháp có thể sửa riêng, xác định trường nào và cấu trúc lồng nào cần tách. Việc chọn toReversed chỉ giải quyết lớp mảng ngoài.

3. slice().reverse() khác toReversed ở ô trống

const sparse = [, 'A'];
const viaSlice = sparse.slice().reverse();
const viaCopy = sparse.toReversed();
console.log(viaSlice[0]); // A
console.log(1 in viaSlice); // false
console.log(1 in viaCopy); // true
console.log(viaCopy[1] === undefined); // true
console.log(JSON.stringify(viaSlice) === JSON.stringify(viaCopy)); // true

Với mảng thưa thông thường này, slice giữ ô trống và reverse đưa nó sang vị trí đối xứng. toReversed đọc ô trống thành undefined, tạo mảng đặc. Hai đầu ra cùng có chuỗi JSON ["A",null] nhưng khác sự tồn tại của thuộc tính chỉ mục 1.

Vì vậy, slice().reverse() là một lựa chọn để tạo mảng đảo mới trên mảng thường, nhưng không nên gọi nó tương đương hoàn toàn với toReversed cho mọi đầu vào. Các ví dụ không xét subclass, getter tùy biến, Proxy hoặc thay đổi prototype.

4. Kiểm tra môi trường trước khi đổi phương thức

Trước khi dùng toReversed, đối chiếu hỗ trợ của runtime và trình duyệt mục tiêu. Kiểm tra tại nơi chạy ứng dụng, không chỉ máy phát triển. Nếu cần cách thay thế, xác nhận contract về mảng thưa và đối tượng đặc biệt thay vì chỉ kiểm tra thứ tự của một mảng chuỗi.

Đảo một trang dữ liệu từ API cũng chỉ đảo các phần tử đã tải. Nó không thay đổi tiêu chí sắp xếp phía server hoặc bảo đảm thứ tự toàn bộ danh sách phân trang. Khi yêu cầu là “mới nhất trước”, thống nhất tiêu chí ở nguồn dữ liệu và cách phân trang.

5. Checklist trước khi đảo danh sách

  • Có được phép sửa mảng nguồn không?
  • Các tham chiếu khác có đang dùng cùng mảng?
  • Cần mảng ngoài mới hay bản sao độc lập của từng object?
  • Có cho phép ô trống và có cần giữ nguyên cấu trúc?
  • Runtime mục tiêu đã hỗ trợ phương thức được chọn?

Sáu khối mã Việt–Anh đã chạy bằng Node.js 24.14.1, kèm kiểm tra mảng rỗng, một phần tử, mảng nguồn bị freeze và cấu trúc ô trống. Chưa kiểm thử giao diện hoặc ma trận trình duyệt thực tế.

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.