Cách sử dụng toán tử typeof trong JavaScript

Javascript căn bản | by Học Javascript

Trong JavaScript, việc kiểm tra kiểu dữ liệu của một biến là rất quan trọng để tránh lỗi và đảm bảo chương trình hoạt động đúng cách. Toán tử typeof là một công cụ hữu ích giúp lập trình viên xác định kiểu dữ liệu của một giá trị một cách nhanh chóng và đơn giản. Với cú pháp ngắn gọn, typeof có thể kiểm tra các kiểu dữ liệu nguyên thủy như string, number, boolean hay các kiểu dữ liệu tham chiếu như object, function.

Tuy nhiên, typeof cũng có một số hạn chế, chẳng hạn như việc trả về "object" cho null hoặc không thể phân biệt rõ ràng giữa mảng và object. Vậy typeof hoạt động như thế nào? Khi nào nên sử dụng? Bài viết này sẽ giúp bạn hiểu rõ hơn về cách sử dụng typeof, các trường hợp đặc biệt và ứng dụng thực tế của nó trong lập trình JavaScript.

Toán tử typeof trong JavaScript

Toán tử typeof trong JavaScript là một công cụ hữu ích giúp kiểm tra kiểu dữ liệu của một biến hoặc giá trị. Đây là một toán tử một ngôi (unary operator), nghĩa là nó chỉ cần một toán hạng để hoạt động. Kết quả của typeof luôn là một chuỗi (string) mô tả loại dữ liệu của toán hạng được kiểm tra.

Cú pháp của typeof

typeof operand

Hoặc:

typeof (operand)

Trong đó, operand có thể là một biến, giá trị hoặc một biểu thức cần kiểm tra.

Ví dụ:

console.log(typeof "Hello");    // "string"
console.log(typeof 42);         // "number"
console.log(typeof true);       // "boolean"
console.log(typeof {});         // "object"
console.log(typeof function(){}); // "function"
console.log(typeof undefined);  // "undefined"

Vai trò của typeof trong kiểm tra kiểu dữ liệu

Toán tử typeof đóng vai trò quan trọng trong việc kiểm tra và xử lý dữ liệu trong JavaScript. Dưới đây là một số lý do chính khiến typeof trở nên hữu ích:

Giúp kiểm tra kiểu dữ liệu động của JavaScript

JavaScript là một ngôn ngữ có kiểu dữ liệu động (dynamic typing), nghĩa là một biến có thể thay đổi kiểu dữ liệu trong suốt thời gian chạy chương trình. Toán tử typeof giúp kiểm tra kiểu dữ liệu của một biến trước khi thực hiện các thao tác, tránh lỗi do không phù hợp kiểu dữ liệu.

Ví dụ:

let x = "Hello";
console.log(typeof x); // "string"
x = 123;
console.log(typeof x); // "number"

Hỗ trợ kiểm tra giá trị undefined

Khi một biến chưa được gán giá trị, nó có kiểu undefined. Sử dụng typeof giúp kiểm tra sự tồn tại của một biến mà không gây lỗi.

Ví dụ:

let user;
console.log(typeof user); // "undefined"

console.log(typeof unknownVar); // "undefined" (Không gây lỗi ngay cả khi biến chưa được khai báo)

Kiểm tra trước khi gọi hàm hoặc truy cập thuộc tính

Để tránh lỗi khi gọi một hàm hoặc truy cập một thuộc tính không tồn tại, typeof có thể được sử dụng để kiểm tra trước.

Ví dụ:

if (typeof myFunction === "function") {
    myFunction();
} else {
    console.log("myFunction không tồn tại!");
}

Phát hiện kiểu dữ liệu đặc biệt (null, function)

  • typeof null trả về "object", đây là một lỗi trong JavaScript từ lâu nhưng vẫn được giữ lại vì lý do tương thích.
  • typeof function() {} trả về "function", giúp phân biệt hàm với các kiểu dữ liệu khác.

Ví dụ:

console.log(typeof null);       // "object" (Lỗi lịch sử của JavaScript)
console.log(typeof function(){}); // "function"

Ứng dụng thực tế của typeof

Xác định kiểu dữ liệu trước khi thực hiện phép toán

Khi nhận dữ liệu từ người dùng hoặc từ API, typeof có thể được sử dụng để kiểm tra kiểu dữ liệu trước khi thao tác, tránh lỗi.

Ví dụ:

function addNumbers(a, b) {
    if (typeof a === "number" && typeof b === "number") {
        return a + b;
    } else {
        return "Vui lòng nhập số!";
    }
}

console.log(addNumbers(5, 10)); // 15
console.log(addNumbers(5, "10")); // "Vui lòng nhập số!"

Kiểm tra sự tồn tại của biến trước khi sử dụng

typeof giúp kiểm tra một biến có tồn tại hay không mà không gây lỗi khi truy cập biến chưa khai báo.

Ví dụ:

if (typeof myVariable !== "undefined") {
    console.log("myVariable đã được khai báo!");
} else {
    console.log("myVariable chưa được khai báo!");
}

Xử lý dữ liệu từ API hoặc JSON

Khi nhận dữ liệu từ API, chúng ta có thể sử dụng typeof để kiểm tra kiểu dữ liệu và xử lý phù hợp.

Ví dụ:

let data = JSON.parse('{ "age": 25 }');

if (typeof data.age === "number") {
    console.log("Tuổi hợp lệ:", data.age);
} else {
    console.log("Dữ liệu không hợp lệ!");
}

Phân loại dữ liệu trong lập trình

Toán tử typeof giúp phân loại dữ liệu trong các chương trình cần xử lý nhiều loại dữ liệu khác nhau.

Ví dụ:

function processData(value) {
    switch (typeof value) {
        case "string":
            console.log("Dữ liệu là chuỗi:", value);
            break;
        case "number":
            console.log("Dữ liệu là số:", value);
            break;
        case "boolean":
            console.log("Dữ liệu là boolean:", value);
            break;
        case "object":
            console.log("Dữ liệu là object:", value);
            break;
        default:
            console.log("Kiểu dữ liệu không xác định!");
    }
}

processData("Hello");   // "Dữ liệu là chuỗi: Hello"
processData(42);        // "Dữ liệu là số: 42"
processData(true);      // "Dữ liệu là boolean: true"
processData({ name: "Alice" }); // "Dữ liệu là object: [object Object]"

Cách sử dụng toán tử typeof trong JavaScript

Toán tử typeof trong JavaScript được sử dụng để kiểm tra kiểu dữ liệu của một biến hoặc giá trị. Nó giúp lập trình viên xác định loại dữ liệu đang làm việc, đặc biệt hữu ích khi xử lý các giá trị không xác định hoặc kiểm tra kiểu dữ liệu trước khi thực hiện các thao tác cụ thể.

Cú pháp của typeof

Toán tử typeof có thể được sử dụng theo hai cách:

typeof operand

Hoặc:

typeof (operand)

Trong đó, operand có thể là một biến, giá trị hoặc một biểu thức cần kiểm tra kiểu dữ liệu.

Ví dụ:

console.log(typeof "Hello");    // "string"
console.log(typeof 42);         // "number"
console.log(typeof true);       // "boolean"
console.log(typeof {});         // "object"
console.log(typeof function(){}); // "function"
console.log(typeof undefined);  // "undefined"

typeof trả về giá trị kiểu chuỗi (string)

Giá trị trả về của typeof luôn là một chuỗi (string) mô tả kiểu dữ liệu của operand. Dưới đây là các kiểu dữ liệu mà typeof có thể trả về:

Giá trị kiểm tra Kết quả trả về của typeof
"Hello" "string"
42 "number"
true / false "boolean"
undefined "undefined"
null "object" (Lỗi lịch sử)
{} (Object) "object"
[] (Array) "object"
function() {} (Hàm) "function"
Symbol("id") "symbol"
BigInt(9007199254740991) "bigint"

Lưu ý đặc biệt:

  • typeof null trả về "object", đây là một lỗi trong JavaScript từ lâu nhưng vẫn được giữ lại vì lý do tương thích.
  • Mảng ([]) cũng trả về "object", vì mảng thực chất là một dạng object đặc biệt trong JavaScript.

Ví dụ minh họa về cách sử dụng typeof

Kiểm tra kiểu dữ liệu của các giá trị khác nhau

console.log(typeof "JavaScript");   // "string"
console.log(typeof 100);            // "number"
console.log(typeof true);           // "boolean"
console.log(typeof undefined);      // "undefined"
console.log(typeof { name: "Alice" }); // "object"
console.log(typeof [1, 2, 3]);      // "object"
console.log(typeof function() {});  // "function"
console.log(typeof Symbol("id"));   // "symbol"
console.log(typeof BigInt(123456789123456789)); // "bigint"

Kiểm tra kiểu dữ liệu trước khi thực hiện thao tác

function addNumbers(a, b) {
    if (typeof a === "number" && typeof b === "number") {
        return a + b;
    } else {
        return "Vui lòng nhập hai số!";
    }
}

console.log(addNumbers(10, 20));  // 30
console.log(addNumbers(10, "20")); // "Vui lòng nhập hai số!"

Kiểm tra biến chưa khai báo mà không bị lỗi

if (typeof unknownVariable === "undefined") {
    console.log("Biến chưa được khai báo!");
}

Đoạn mã trên không gây lỗi ngay cả khi unknownVariable chưa được khai báo, giúp tránh lỗi runtime.

Kiểm tra kiểu dữ liệu của nullarray

console.log(typeof null);  // "object" (Lỗi lịch sử trong JavaScript)
console.log(typeof []);    // "object" (Mảng thực chất là một object)

Kiểm tra kiểu dữ liệu trước khi gọi hàm

let myFunction = function() {
    console.log("Đây là một hàm!");
};

if (typeof myFunction === "function") {
    myFunction(); // Gọi hàm nếu nó thực sự là một function
} else {
    console.log("Đây không phải là một hàm!");
}

Kiểm tra kiểu dữ liệu từ API hoặc JSON

let data = JSON.parse('{ "age": 25 }');

if (typeof data.age === "number") {
    console.log("Tuổi hợp lệ:", data.age);
} else {
    console.log("Dữ liệu không hợp lệ!");
}

Các kiểu dữ liệu và giá trị trả về của typeof trong JavaScript

Toán tử typeof trong JavaScript giúp kiểm tra kiểu dữ liệu của một giá trị và trả về một chuỗi (string) mô tả kiểu dữ liệu đó. JavaScript có hai nhóm kiểu dữ liệu chính: Dữ liệu nguyên thủy (Primitive Types)Dữ liệu tham chiếu (Reference Types). Dưới đây là chi tiết về cách typeof hoạt động với từng loại dữ liệu.

Dữ liệu nguyên thủy (Primitive Types)

Dữ liệu nguyên thủy là những giá trị không thể thay đổi (immutable) và được lưu trực tiếp trong bộ nhớ. JavaScript có 6 loại dữ liệu nguyên thủy:

Chuỗi (String)

Chuỗi trong JavaScript là một tập hợp các ký tự Unicode, được đặt trong dấu nháy đơn ('), dấu nháy đôi (") hoặc dấu template (``).

console.log(typeof "Hello");  // "string"
console.log(typeof 'JavaScript');  // "string"
console.log(typeof `Template String`);  // "string"

Số (Number)

Kiểu number bao gồm cả số nguyên và số thực (số dấu chấm động).

console.log(typeof 123);  // "number"
console.log(typeof 3.14);  // "number"
console.log(typeof -42);  // "number"
console.log(typeof NaN);  // "number" (NaN là một giá trị số đặc biệt)

Lưu ý: NaN (Not a Number) vẫn được coi là kiểu "number".

Boolean

Kiểu boolean chỉ có hai giá trị: truefalse.

console.log(typeof true);  // "boolean"
console.log(typeof false);  // "boolean"

Undefined

Khi một biến được khai báo nhưng chưa gán giá trị, nó có kiểu undefined.

let x;
console.log(typeof x);  // "undefined"

console.log(typeof undefined);  // "undefined"

Symbol (ES6)

Symbol là một kiểu dữ liệu duy nhất được thêm vào từ ECMAScript 6 (ES6). Nó được sử dụng để tạo ra các giá trị duy nhất.

const id = Symbol('id');
console.log(typeof id);  // "symbol"

BigInt (ES11)

BigInt là kiểu dữ liệu mới từ ES11 (ES2020), dùng để lưu trữ số nguyên rất lớn.

const bigNumber = BigInt(9007199254740991);
console.log(typeof bigNumber);  // "bigint"

console.log(typeof 10n);  // "bigint"

Dữ liệu tham chiếu (Reference Types) trong JavaScript

Dữ liệu tham chiếu là những giá trị phức tạp, không được lưu trực tiếp trong biến mà thay vào đó, biến chứa địa chỉ của vùng nhớ nơi dữ liệu được lưu trữ.

Object (Đối tượng)

Đối tượng (Object) trong JavaScript là một tập hợp các cặp key-value.

console.log(typeof {});  // "object"

const person = { name: "Alice", age: 25 };
console.log(typeof person);  // "object"

Array (Mảng)

Mảng (Array) cũng là một dạng của Object.

console.log(typeof [1, 2, 3]);  // "object"

const numbers = [10, 20, 30];
console.log(typeof numbers);  // "object"

Lưu ý: typeof không phân biệt được giữa ObjectArray, cả hai đều trả về "object". Để kiểm tra một giá trị có phải là mảng hay không, hãy sử dụng Array.isArray():

console.log(Array.isArray([1, 2, 3]));  // true
console.log(Array.isArray({}));  // false

Function (Hàm)

Hàm trong JavaScript được coi là một Object đặc biệt, nhưng typeof trả về "function".

console.log(typeof function() {});  // "function"

const greet = () => "Hello!";
console.log(typeof greet);  // "function"

null – Trường hợp đặc biệt

null là một giá trị đặc biệt trong JavaScript, đại diện cho "không có giá trị". Tuy nhiên, do lỗi trong thiết kế ban đầu của JavaScript, typeof null trả về "object".

console.log(typeof null);  // "object" (Lỗi lịch sử của JavaScript)
Cách kiểm tra chính xác nếu một biến có giá trị null:
console.log(null === null);  // true
console.log(value === null);  // true (nếu value có giá trị null)
Giá trị Giá trị trả về của typeof
"Hello" "string"
123 "number"
true / false "boolean"
undefined "undefined"
Symbol('id') "symbol"
BigInt(10) "bigint"
{} (Object) "object"
[] (Array) "object"
function() {} (Function) "function"
null "object" (Lỗi của JS)

Ví minh họa chi tiết với từng kiểu dữ liệu

console.log(typeof "JavaScript");   // "string"
console.log(typeof 100);            // "number"
console.log(typeof true);           // "boolean"
console.log(typeof undefined);      // "undefined"
console.log(typeof Symbol("id"));   // "symbol"
console.log(typeof BigInt(123456789)); // "bigint"

console.log(typeof {});             // "object"
console.log(typeof [1, 2, 3]);      // "object"
console.log(typeof function(){});   // "function"
console.log(typeof null);           // "object" (Lỗi lịch sử)

console.log(typeof NaN);            // "number"
console.log(typeof 10n);            // "bigint"

let variable;
console.log(typeof variable);       // "undefined"

console.log(typeof new Date());     // "object"
console.log(typeof /regex/);        // "object"

Những trường hợp đặc biệt của typeof trong JavaScript

Toán tử typeof trong JavaScript đôi khi có những kết quả không như mong đợi do các đặc điểm thiết kế ban đầu của ngôn ngữ. Dưới đây là những trường hợp đặc biệt cần lưu ý khi sử dụng typeof.

typeof null trả về "object" – Lỗi trong JavaScript

Một trong những lỗi lịch sử nổi tiếng của JavaScript là khi kiểm tra typeof null, kết quả trả về "object". Điều này có thể gây nhầm lẫn, vì null không phải là một Object.

Ví dụ

console.log(typeof null);  // "object"

Giải thích

  • Khi JavaScript được phát triển vào năm 1995, kiểu dữ liệu trong bộ nhớ được lưu bằng cách sử dụng tagging system (hệ thống đánh dấu).
  • null được biểu diễn bằng tất cả các bit 0 (00000000), giống như cách các object được nhận diện.
  • Điều này dẫn đến việc typeof null trả về "object", mặc dù thực tế null không phải là một Object.

Cách kiểm tra chính xác null

Do lỗi này, thay vì dùng typeof, hãy sử dụng phép so sánh trực tiếp:

console.log(null === null);  // true
console.log(value === null);  // true (nếu value là null)
Hoặc sử dụng Object.prototype.toString.call():
console.log(Object.prototype.toString.call(null));  // "[object Null]"

typeof NaN trả về "number" mặc dù NaN không phải số hợp lệ

NaN (Not a Number) là một giá trị đặc biệt trong JavaScript đại diện cho kết quả không hợp lệ của phép toán số học. Tuy nhiên, typeof NaN vẫn trả về "number".

Ví dụ

console.log(typeof NaN);  // "number"
console.log(NaN === NaN);  // false (NaN không bao giờ bằng chính nó)
  • JavaScript coi NaN là một giá trị số hợp lệ trong phạm vi kiểu number.
  • Nhưng NaN thực tế không phải là một số hợp lệ, vì nó biểu diễn một kết quả không xác định của phép toán số học (ví dụ: chia 0 cho 0, căn bậc hai của số âm…).

Cách kiểm tra chính xác NaN

Do NaN không bằng chính nó (NaN === NaN trả về false), bạn có thể kiểm tra NaN bằng cách:

console.log(isNaN(NaN));  // true
console.log(isNaN(123));  // false

Hoặc sử dụng phương thức Number.isNaN() (giới thiệu từ ES6), giúp kiểm tra chính xác hơn:

console.log(Number.isNaN(NaN));  // true
console.log(Number.isNaN("hello"));  // false (vì "hello" không phải số, nhưng không phải NaN)

typeof [] và typeof {} đều trả về "object", cách phân biệt chúng

Cả mảng (Array)đối tượng (Object) trong JavaScript đều được coi là kiểu "object", nhưng chúng có các đặc điểm khác nhau.

Ví dụ

console.log(typeof {});  // "object"
console.log(typeof []);  // "object"

Cách phân biệt Object và Array

Do typeof không phân biệt được ObjectArray, hãy dùng phương thức Array.isArray() để kiểm tra:

console.log(Array.isArray({}));  // false ({} là object)
console.log(Array.isArray([]));  // true ([] là array)

Hoặc sử dụng Object.prototype.toString.call() để kiểm tra chính xác kiểu dữ liệu:

console.log(Object.prototype.toString.call({}));  // "[object Object]"
console.log(Object.prototype.toString.call([]));  // "[object Array]"

typeof function() {} trả về "function" thay vì "object"

Hàm (Function) trong JavaScript thực chất là một Object đặc biệt, nhưng typeof lại trả về "function" thay vì "object".

Ví dụ

console.log(typeof function() {});  // "function"
console.log(typeof (() => {}));  // "function"

Giải thích

  • JavaScript thiết kế typeof trả về "function" để lập trình viên dễ nhận biết các hàm hơn.
  • Thực chất, trong JavaScript, mọi hàm đều là một Object và có thể chứa các thuộc tính giống như một Object.

Ví dụ:

function sayHello() {}
sayHello.message = "Hello, world!";

console.log(typeof sayHello);  // "function"
console.log(sayHello.message);  // "Hello, world!"
console.log(sayHello instanceof Object);  // true (Vì function là một Object)

Kiểm tra chính xác kiểu dữ liệu của hàm

Sử dụng Object.prototype.toString.call():

console.log(Object.prototype.toString.call(function() {}));  // "[object Function]"
console.log(Object.prototype.toString.call(() => {}));  // "[object Function]"

Kết bài

Toán tử typeof là một công cụ đơn giản nhưng quan trọng trong JavaScript, giúp lập trình viên kiểm tra kiểu dữ liệu một cách nhanh chóng. Nó đặc biệt hữu ích khi xác định loại biến trước khi thực hiện các phép toán hoặc xử lý dữ liệu đầu vào.

Tuy nhiên, typeof cũng có một số hạn chế, đặc biệt là không thể phân biệt chính xác giữa null, array, và object. Để khắc phục những hạn chế này, ta có thể kết hợp Array.isArray(), Object.prototype.toString.call(), và instanceof để kiểm tra kiểu dữ liệu một cách chính xác hơn.

Hiểu rõ cách sử dụng typeof và các giải pháp thay thế phù hợp sẽ giúp lập trình viên viết code hiệu quả, giảm thiểu lỗi, và xây dựng các ứng dụng JavaScript mạnh mẽ hơn.

Bài viết liên quan