aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

JavaScript sort: vì sao số 10 đứng trước 2 và mảng gốc bị đổi?

Suong Nguyen by Suong Nguyen
26/10/2026
in Phỏng vấn
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Bạn gọi sort cho một mảng số rồi thấy 10 đứng trước 2. Sau đó, một biến khác cùng trỏ vào mảng cũng thay đổi dù không gọi sort trên biến đó. Đây là hai hành vi khác nhau cần giải thích: cách so sánh mặc định và việc sắp xếp tại chỗ.

Các ví dụ trong bài đã chạy bằng Node.js 24.18.1, tài liệu MDN được đối chiếu ngày 26/10/2026. Chúng chỉ kiểm tra ngữ nghĩa và kết quả của dữ liệu nhỏ; không có benchmark tốc độ hoặc cam kết một thuật toán sort cụ thể trong mọi engine.

1. Sort mặc định không suy ra ý định số học

Theo MDN về Array.sort, cách sắp xếp mặc định chuyển phần tử thành chuỗi rồi so sánh theo các đơn vị mã UTF-16. Sort cũng thay đổi mảng và trả lại cùng tham chiếu.

Lưu thành sort-demo.mjs rồi chạy bằng Node:

const numbers = [2, 10, 1];
const alias = numbers;
const result = numbers.sort();

console.log(numbers.join(','));
console.log(result === numbers, alias === numbers);
console.log(alias.join(','));

numbers.sort((a, b) => a - b);
console.log(numbers.join(','));

Output đã kiểm tra là 1,10,2, true true, 1,10,2, rồi 1,2,10. Comparator số học diễn đạt thứ tự tăng dần cần dùng; gán kết quả sort vào một biến mới không tạo ra bản sao để bảo vệ biến cũ.

Ví dụ chỉ dùng số hữu hạn đã biết. Nếu dữ liệu còn chứa string, null hoặc NaN, hãy xác định và kiểm tra kiểu trước khi áp dụng phép trừ. Một comparator ngắn chưa thay thế validation đầu vào.

2. Comparator phải trả một quan hệ nhất quán

Kết quả âm cho biết a đứng trước b, dương cho biết a đứng sau b, còn 0 cho biết bằng nhau theo tiêu chí đang xét. Trả boolean từ a > b không mô tả đầy đủ quan hệ đó:

const badCompare = (a, b) => a > b;
console.log(badCompare(1, 2), badCompare(2, 1));

Output là false true. Khi được dùng như kết quả số, cặp đó tương ứng 0 và 1 thay vì hai dấu đối nhau. Tài liệu sort giải thích comparator không đáp ứng hợp đồng có thể cho hành vi khác giữa các engine. Vì vậy bài không dùng một output sort từ comparator sai làm đáp án chung cho mọi JavaScript runtime.

Không sửa mảng, gọi request hay thay state bên ngoài trong comparator. Bạn không nên dựa vào số lần hoặc thứ tự engine gọi nó. Với quy tắc nhiều tiêu chí, viết chúng thành thứ tự rõ ràng rồi thử các cặp bằng nhau và đảo vị trí.

3. Dùng toSorted khi cần một mảng kết quả mới

Array.toSorted là biến thể trả mảng mới. Ví dụ sau đã được chạy trên Node 24.18.1:

const input = [2, 10, 1];
const ascending = input.toSorted((a, b) => a - b);
console.log(input.join(','));
console.log(ascending.join(','));
console.log(input === ascending);

Kết quả là 2,10,1, 1,2,10, rồi false. Nếu môi trường mục tiêu chưa hỗ trợ toSorted, có thể tạo một mảng mới trước khi sort theo cách phù hợp dự án. Cả hai cách tạo mảng mới đều không tự deep clone các object bên trong.

Với state của UI, điều bạn muốn thường là một giá trị mảng mới cho kết quả hiển thị mà không đổi thứ tự nguồn đang được nơi khác dùng. Hãy kiểm tra cả mảng nguồn lẫn mảng kết quả để tránh chỉ nhìn giao diện cuối cùng.

4. Tính ổn định và tiêu chí phụ

Trong JavaScript hiện đại, sort ổn định giữ thứ tự tương đối của các phần tử bằng nhau theo comparator. Tuy vậy, nếu yêu cầu sản phẩm là ưu tiên lớn trước rồi ID nhỏ trước, cần viết tiêu chí ID thay vì dựa vào thứ tự đầu vào tình cờ:

const tasks = [
  {id: 2, priority: 5},
  {id: 1, priority: 5},
  {id: 3, priority: 1},
];

const byPriority = tasks.toSorted((a, b) => b.priority - a.priority);
const withTieBreak = tasks.toSorted(
  (a, b) => b.priority - a.priority || a.id - b.id,
);
console.log(byPriority.map(x => x.id).join(','));
console.log(withTieBreak.map(x => x.id).join(','));

Output đã kiểm tra là 2,1,3, rồi 1,2,3. Trong bản đầu, hai mục priority bằng nhau giữ thứ tự nhập. Trong bản sau, phép so sánh ID quyết định thứ tự khi priority bằng nhau. Chỉ dùng ID dạng số ở đây vì đó là hợp đồng fixture.

Kiểm tra và lỗi thường gặp

Tạo ca có mảng rỗng, một phần tử, phần tử bằng nhau, thứ tự đã đúng và thứ tự đảo ngược. Với comparator nhiều tiêu chí, thêm ca hòa ở tiêu chí đầu. Xác nhận comparator trả 0 cho cùng một đối tượng và kết quả đối xứng dấu cho hai giá trị khác nhau trong phạm vi dữ liệu hợp lệ.

Đừng xem “trên máy tôi vẫn đúng” là bằng chứng comparator sai hợp đồng có thể dùng. Cũng đừng thay sort bằng toSorted rồi bỏ qua kiểu dữ liệu; nó đổi chính sách mutation, không tự sửa ý nghĩa so sánh.

Gợi ý trả lời phỏng vấn

Hãy trình bày thứ tự mặc định, tác động lên mảng gốc, vai trò comparator và cách xử lý giá trị bằng nhau. Sau đó chạy một fixture nhỏ để chứng minh từng ý. Một lời giải giải thích được hợp đồng sẽ hữu ích hơn việc chỉ nhớ (a, b) => a - b.

Nguồn tham khảo

  • MDN: Array.sort
  • MDN: Array.toSorted

Tags: ArrayJavaScriptPhỏng vấn
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

JavaScript: chọn giá trị mặc định mà không làm mất 0, false và chuỗi rỗng

by Suong Nguyen
25/10/2026
0

Phân biệt toán tử OR, nullish coalescing và optional chaining bằng ví dụ chạy được cùng các trường hợp dễ nhầm khi đọc cấu hình.

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Promise.all và allSettled: chờ kết quả không có nghĩa là tự hủy tác vụ

by Suong Nguyen
24/10/2026
0

Chạy ví dụ nhỏ để phân biệt Promise.all, allSettled, thứ tự kết quả và việc hủy công việc khi một promise thất bại.

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Phỏng vấn JavaScript: vì sao spread vẫn có thể làm đổi object gốc?

by Suong Nguyen
23/10/2026
0

Luyện cách giải thích shallow copy, so sánh tham chiếu và cập nhật một nhánh dữ liệu mà vẫn giữ object ban đầu.

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Phỏng vấn JavaScript: giải thích event loop, microtask và async/await

by Suong Nguyen
22/10/2026
0

Luyện cách giải thích thứ tự chạy của Promise, timer và await thay vì chỉ học thuộc đáp án in ra màn hình.

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native Image: cover và contain khác nhau trong cùng một khung ảnh
  • JavaScript sort: vì sao số 10 đứng trước 2 và mảng gốc bị đổi?
  • Android plurals: vì sao getQuantityString cần truyền count hai lần?

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply