JavaScript Data Types: Hiểu Để Không Bị "Type Coercion" Điều Khiển

Programing Sep 5, 2025

Khi lập trình JavaScript, chắc chắn bạn đã từng gặp những trường hợp "dở khóc dở cười" khi so sánh các giá trị. JavaScript không phải là một ngôn ngữ "strictly typed", chính vì thế việc hiểu rõ từ undefined đến Symbol sẽ giúp bạn tránh được những bug "ngớ ngẩn" mà 99% lập trình viên đều từng mắc phải.

1. Có bao nhiêu kiểu dữ liệu trong JavaScript?

JavaScript phân loại các kiểu dữ liệu thành hai nhóm chính:

1.1 Primitive types (Kiểu nguyên thủy)

Đây là các kiểu dữ liệu cơ bản, được lưu trữ trực tiếp trong Stack:

  • undefined
  • null
  • boolean
  • number
  • string
  • bigint (ES2020)
  • symbol (ES6)

1.2 Non-primitive types (Kiểu tham chiếu)

Chỉ có một kiểu non-primitive duy nhất là Object, nhưng nó bao gồm:

  • Object literal: { }
  • Array: [ ]
  • Function: function() { }
  • Date, RegExp, v.v.
Tip: Bạn có thể kiểm tra kiểu giá trị bằng toán tử typeof. Tuy nhiên, typeof null === 'object' là một bug "huyền thoại" tồn tại từ thuở sơ khai của JavaScript mà bạn cần lưu ý.

2. typeof — Đừng quá tin tưởng

  • typeof null // "object" ← Bug kinh điển
  • typeof NaN // "number" ← Số nhưng lại là "Not a Number"
  • typeof [] // "object" ← Không phân biệt được với object thường
  • typeof (() => {}) // "function" ← OK

Lời khuyên: Để kiểm tra Array, hãy dùng Array.isArray(value) thay vì typeof.

3. Sự khác biệt giữa undefined và null

  • let a; (Khai báo nhưng chưa gán giá trị) → aundefined.
  • let b = null; (Chủ động gán giá trị "trống") → bnull.

Bug thường gặp: So sánh bằng toán tử == giữa nullundefined trả về true, nhưng === thì không.

JavaScript

null == undefined     // true
null === undefined    // false

4. So sánh == vs === — "Kẻ hủy diệt" hệ thống

Việc ép kiểu tự động (coercion) của JavaScript khi dùng == có thể dẫn tới những kết quả không tưởng:

  • 0 == false // true
  • "" == false // true
  • [] == false // true
  • [] == ![] // true ← 🤔???

Lời khuyên: Luôn luôn sử dụng === để tránh những kết quả kỳ lạ do việc ép kiểu tự động gây ra.

5. Symbol và BigInt — Những "người lạ" ít dùng

Symbol

Tạo ra một định danh duy nhất (unique) và không thể trùng lặp.

JavaScript

const id1 = Symbol('id');
const id2 = Symbol('id');
console.log(id1 === id2);   // false
  • Use case: Tạo các key ẩn cho object hoặc enum an toàn, tránh xung đột tên.

BigInt

Dùng cho các số nguyên cực lớn vượt quá giới hạn an toàn của Number.

JavaScript

const max = BigInt(Number.MAX_SAFE_INTEGER);
console.log(max + 1n); // Hoạt động tốt

// Lưu ý: Không thể trộn lẫn BigInt với Number thường
// 123 + 1n  → Error!

6. Các lỗi kinh điển trong thực tế

1. Object vs Array

Cả hai đều trả về "object" khi dùng typeof.

  • Bug thường gặp: Xử lý Array như một Object (hoặc ngược lại) khi thực hiện deep clone hoặc vòng lặp.

2. Falsy values

Các giá trị được coi là false trong câu lệnh điều kiện: false, 0, "", null, undefined, NaN.

JavaScript

const values = [false, 0, "", null, undefined, NaN];

values.forEach(v => {
  if (!v) {
    console.log(`"${v}" là falsy`);
  }
});

Tip: Nếu bạn cần kiểm tra chính xác null hoặc undefined, đừng dùng if (!value), hãy dùng value === null || value === undefined.

7. JSON và những cái bẫy

Dữ liệu có thể bị mất mát khi bạn dùng JSON.stringify():

  • JSON.stringify(undefined) // undefined
  • JSON.stringify({ a: undefined }) // "{}" (Key 'a' biến mất)
  • JSON.stringify([undefined]) // "[null]" (Chuyển thành null)

Lưu ý: undefined không thể được stringify hoàn chỉnh, điều này dễ dẫn đến mất dữ liệu khi gửi POST API.

8. Tổng kết kinh nghiệm

  1. Dùng typeof cho các kiểu nguyên thủy (string, number, boolean,...).
  2. Dùng Array.isArray() cho Array.
  3. Tránh dùng typeof null, typeof [], typeof NaN.
  4. Dùng == null nếu muốn bắt cả nullundefined.
  5. Luôn dùng === để so sánh giá trị.

JavaScript không bắt lỗi kiểu dữ liệu lúc viết code, nhưng nó rất dễ làm ứng dụng của bạn "bay màu" chỉ vì một lỗi ép kiểu vô tình. Kiểm soát được kiểu dữ liệu là bạn đã kiểm soát được 50% độ ổn định của ứng dụng.

Cảm ơn bạn đã đọc bài viết! Hãy luôn hoài nghi mọi phép so sánh trong JavaScript nhé.

Tags