Đổi map(value => parseInt(value, 10)) thành map(parseInt) làm danh sách số xuất hiện NaN. Đây là thay đổi cách truyền tham số, không chỉ rút gọn cú pháp. Một hàm dùng tốt khi gọi trực tiếp chưa chắc tương thích với hợp đồng callback của phương thức mảng.
1. Một đầu vào đúng vẫn có thể ra kết quả sai
const values = ['1', '2', '3'];
const result = values.map(parseInt);
console.log(result.map(String).join(',')); // 1,NaN,NaN
console.log(parseInt('2', 10)); // 2
Ví dụ không dùng JSON.stringify để hiển thị kết quả vì NaN trong mảng sẽ được chuyển thành null khi xuất JSON. Cách in từng giá trị thành chuỗi giúp thấy đúng vấn đề đang kiểm tra.
2. map truyền cả chỉ mục và mảng nguồn
const values = ['1', '2', '3'];
const received = [];
values.map((value, index, array) => {
received.push(`${value}:${index}:${array === values}`);
return value;
});
console.log(received.join('|')); // 1:0:true|2:1:true|3:2:true
Callback nhận lần lượt value, index và array. Trong khi đó, parseInt đọc hai tham số đầu như chuỗi và radix. Vì vậy ba lượt gọi tương ứng với parseInt('1', 0), parseInt('2', 1) và parseInt('3', 2).
Radix bằng 0 cho phép suy ra cơ số; với '1' kết quả là 1. Cơ số 1 không hợp lệ. Trong cơ số 2, chữ số '3' không hợp lệ. Hai lượt sau trả NaN. Vấn đề không nằm ở việc chuỗi '2' và '3' có phải chữ số thập phân hay không.
3. Viết lớp nối tham số rõ ràng
const values = ['1', '2', '3'];
const result = values.map(value => parseInt(value, 10));
console.log(result.join(',')); // 1,2,3
console.log(['12px'].map(value => parseInt(value, 10))[0]); // 12
console.log(['', '1e2'].map(Number).join(',')); // 0,100
Arrow function chỉ chuyển value và cơ số 10 do người viết lựa chọn. Tuy nhiên, sửa cách truyền tham số chưa biến parseInt thành validation toàn bộ chuỗi: '12px' vẫn được đọc thành 12. Với dữ liệu cần đúng định dạng, kiểm tra hợp đồng riêng trước khi phân tích.
map(Number) tránh xung đột radix, nhưng ví dụ cho thấy nó nhận chuỗi rỗng thành 0 và ký hiệu số mũ thành 100. Chọn parser theo dữ liệu được phép, đừng thay hàm chỉ để hết NaN. Number.parseInt cũng có tham số radix nên không tự giải quyết lỗi callback.
4. Tham số mặc định cũng có thể bị ghi đè ngoài ý muốn
function formatCode(value, width = 4) {
return value.padStart(width, '0');
}
console.log(['7', '7', '7'].map(formatCode).join(',')); // 7,7,07
console.log(['7', '7', '7'].map(value => formatCode(value)).join(',')); // 0007,0007,0007
formatCode nhận chỉ mục 0, 1, 2 làm width khi được truyền trực tiếp. Mặc định 4 chỉ áp dụng khi tham số width thiếu hoặc là undefined. Wrapper ở dòng sau chủ động không truyền chỉ mục, nên mặc định được dùng.
Đây là ví dụ tự xây dựng để kiểm tra cùng kiểu lỗi bên ngoài parseInt. Khi refactor callback, xem xét cả ý nghĩa của tham số phụ lẫn this và giá trị trả về. Một wrapper ngắn có thể thể hiện rõ ý định hơn việc truyền tên hàm trực tiếp.
5. Review trước khi rút gọn callback
- API gọi callback với những tham số nào, theo thứ tự nào?
- Hàm được truyền vào hiểu các tham số phụ ra sao?
- Chỉ mục có vô tình ghi đè cơ số, độ rộng hoặc tùy chọn không?
- Kiểm thử có nhiều phần tử để chỉ mục vượt khỏi 0 không?
- Sửa callback có giữ nguyên quy tắc validation không?
Tám khối ví dụ Việt–Anh đã chạy bằng Node.js, kèm kiểm tra nhiều chuỗi số và hành vi formatCode. Không kiểm thử biểu mẫu trình duyệt hoặc đo hiệu năng. Tham khảo MDN Array.map và MDN parseInt.




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