JavaScript và Những “Cú Lừa” Thú Vị
JavaScript là ngôn ngữ dễ học, linh hoạt và phổ biến ở cả frontend lẫn backend nhờ Node.js, cho phép xây dựng ứng dụng full stack như MEAN và MERN Stack. Tuy nhiên, JavaScript cũng có những “cú lừa” khó chịu nếu bạn không hiểu rõ các sắc thái của nó.
JavaScript thường được đánh giá là một ngôn ngữ dễ học và linh hoạt. Nhờ vậy, hầu hết các công nghệ web đều sử dụng JavaScript ở phía client. Với sự ra đời của Node.js, JavaScript còn trở thành một ngôn ngữ mạnh mẽ ở phía backend, cho phép xây dựng các ứng dụng full stack như MEAN Stack hay MERN Stack.
Tuy nhiên, giống như mọi ngôn ngữ lập trình khác, JavaScript có những sắc thái riêng mà nếu không hiểu rõ, bạn có thể rơi vào những “cú lừa” khó chịu. Bài viết này sẽ giới thiệu những điểm thú vị và những sai lầm phổ biến khi làm việc với JavaScript.
1. Key của Object luôn là String
Trong JavaScript, key của một object luôn được chuyển về string. Hãy xem ví dụ sau:
var foo = new Object();
var bar = new Object();
var map = new Object();
map[foo] = "foo";
map[bar] = "bar";
console.log(map[foo]); // Kết quả là "bar"
Giải thích:
JavaScript sẽ tự động chuyển key (nếu không phải string) thành string bằng cách gọi toString(). Ở đây, foo.toString() và bar.toString() đều trả về "[object Object]", nên key cuối cùng bị ghi đè.
Tương tự:
var a = {};
var b = { key: "b" };
var c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]); // Kết quả là 456
2. Hoisting và Sự Khác Biệt Giữa Function Statement và Function Expression
Có sự khác biệt giữa hai cách khai báo hàm này:
var foo = function() {}; // Function Expression
function foo() {} // Function Statement
• Function Statement sẽ được “hoist” (đưa khai báo lên đầu scope), nên có thể tham chiếu trước khi khai báo.
• Function Expression thì không được hoist.
Ví dụ:
function foo() { return 1; }
console.log(foo()); // Kết quả là 2
function foo() { return 2; }
Kết quả là 2 vì function statement cuối cùng sẽ được sử dụng.
Ngược lại, với function expression:
var foo = function() { return 1; };
console.log(foo()); // Kết quả là 1
foo = function() { return 2; };
Ở đây, foo giữ nguyên giá trị được gán ban đầu.
3. null Là một Object
JavaScript có một bug từ phiên bản đầu tiên: null được nhận diện là một object.
console.log(typeof null === "object"); // true
Để kiểm tra một giá trị có phải là object không, bạn cần bổ sung điều kiện:
(bar !== null) && (typeof bar === "object");
4. Tự Động Thêm Dấu Chấm Phẩy
Dấu chấm phẩy không bắt buộc trong JavaScript, nhưng đôi khi nó sẽ gây ra lỗi. Hãy xem ví dụ sau:
function foo1() {
return {
bar: "hello"
};
}
function foo2() {
return
{
bar: "hello"
};
}
- foo1() trả về object { bar: "hello" }.
- foo2() lại trả về undefined vì JavaScript tự động thêm dấu chấm phẩy sau từ khóa return.
Bài học: Luôn viết code rõ ràng và nhất quán để tránh các lỗi tương tự.
5. typeof NaN là Number
NaN (Not a Number) biểu thị giá trị không hợp lệ khi thực hiện phép toán số học, nhưng kỳ lạ thay:
console.log(typeof NaN === "number"); // true
console.log(NaN === NaN); // false
Để kiểm tra giá trị có phải là NaN hay không, bạn có thể dùng:
Number.isNaN(value); // Kiểm tra chính xác hơn trong ES6
6. Số Trong JavaScript và Dấu Phẩy Động
Số trong JavaScript được biểu diễn bằng dấu phẩy động, dẫn đến những kết quả không chính xác:
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 == 0.3); // false
Bài học: Hãy cẩn thận khi so sánh và tính toán với số dấu phẩy động trong JavaScript.
Kết Luận
JavaScript là một ngôn ngữ mạnh mẽ và phổ biến, nhưng cũng đầy “cú lừa” thú vị. Hiểu rõ các sắc thái và hạn chế của ngôn ngữ sẽ giúp bạn tránh được các lỗi thường gặp và viết mã hiệu quả hơn. Từ việc quản lý key trong object, hiểu rõ hoisting, đến việc xử lý các phép toán dấu phẩy động, bạn cần cẩn thận và nhất quán trong cách viết code.
Comments ()