Một cách ngắn gọn, chúng ta nên dùng Number(x)
để convert giá trị sang dạng number, hoặc parseFloat(x)
nếu muốn chuẩn mực
Để kiểm tra kết quả có convert được hay không, luôn dùng Number.isNaN()
, không nên dùng phương thức global isNaN()
.
typeof parseFloat('42'); // 'number' Number.isNaN(Number('42')); // false typeof parseFloat('fail'); // 'number' Number.isNaN(Number('fail')); // true
Sử dụng Number(x)
sẽ có vài trường hợp đặc biệt, nó có thể là đúng cũng có thể là sai, tùy theo cách hiểu của chúng ta.
Number(''); // 0
Rất nhiều dev sử dụng +x
để convert giá trị x sang number. Theo như khai báo của javascript, +x
sẽ tương tự như Number(x)
+'42 fail'; // NaN +({ valueOf: () => '42' }); // 42 +({ toString: () => '42' }); // 42 +(null); // 0 +(' '); // 0
Cái sai của Number(x)
Number(x)
và parseFloat(x)
xử trí các tình huống đặc biệt rất khác nhau, parseFloat()
có vẻ dễ giải hơn khi chấp nhận một số kiểu String
Number('42 fail'); // NaN parseFloat('42 fail') // 42 parseInt('42 fail') // 42 Number(' 10') // 10 parseFloat(' 10') // 10 parseInt(' 10') // 10
Đừng thấy vậy mà kết luận rằng Number(x)
chuẩn mực và an toàn hơn. Thực ra, Number(x)
hay lấn cấn khi string chứa khoảng trắng, null
, và một số tính huống khác. Nó convert khá nhiều trường hợp sang 0.
Number(null) // 0 Number('') // 0 Number(' ') // 0 Number(false) // 0 Number({ toString: () => '' }); // 0 Number({ valueOf: () => ' ' }); // 0
Nguyên tắc làm việc của parseFloat()
đơn giản và dễ đoán hơn. Cắt hết khoảng trắng, rồi kiểm tra với một regular expression được quy ước để lấy giá trị số dài nhất trong chuỗi.
// parseInt hoạt động tương tự parseFloat(null); // NaN parseFloat(''); // NaN parseFloat(' '); // NaN parseFloat(false); // NaN parseFloat({ toString: () => '' }); // NaN parseFloat({ valueOf: () => ' ' }); // NaN
Number.isNaN() và isNaN()
Javascript sẽ ko quăng lỗi nếu nó ko convert được giá trị sang number, nó trả về một giá trị đặc biệt gọi là NaN
(not a number). Và vẫn chưa đủ độ huyền bí, nếu kiểm tra typeof
của một giá trị là NaN
chúng ta nhận được ‘number`. Nực cười quá mà.
Number('fail'); // NaN typeof Number('fail') // 'number'
Lý do cho sự có mặt của Number.isNaN()
và isNaN()
là vì ==
và ===
không chạy đúng trên giá trị NaN
Number('fail') == Number('fail'); // false Number('fail') === Number('fail'); // false Number('fail') == NaN; // false NaN === NaN; // false
Number.isNaN()
là một hàm mới được bổ sung trong ES6, tuy nhiên ko nhận được nhiều sự quan tâm. Chúng ta nên tập sử dụng Number.isNaN()
thay cho isNaN()
isNaN(Number('fail')) // true Number.isNaN(Number('fail')); // true
Một cách dễ hình dung sự khác nhau, nếu Number.isNaN()
là so sánh ===
thì isNaN()
là so sánh ==
Thằng isNaN()
nó sẽ convert giá trị qua number trước, rồi mới đem đi so sánh kết quả.
isNaN(‘fail’) // true isNaN({}) // true Number.isNaN(‘fail’) // false Number.isNaN({}) // false
Nói cách khác, nếu giá trị x không phải kiểu number, thì Number.isNaN(x)
sẽ là false
Cái polyfill cho Number.isNaN()
đ
9 tuyệt kỹ “hack” JavaScript mà bạn nên biết
ược hiện thực đơn giản như sau
Number.isNaN = function(x) { return typeof x === 'number' && isNaN(x); }
Bài viết gốc được đăng tải tại VuiLapTrinh
Có thể bạn quan tâm:
- Hỏi ngắn đáp nhanh – Trắc nghiệm JavaScript
- JavaScript và những câu hỏi khó – Part 1
- 9 tuyệt kỹ “hack” JavaScript mà bạn nên biết
Xem thêm các tuyển dụng JavaScript hấp dẫn tại TopDev