Trong JavaScript, mọi thứ đều là một đối tượng (hoặc ít nhất có thể được coi là một đối tượng), ngoại trừ các nguyên hàm (booleans, null, số, chuỗi và giá trị undefined
(và ký hiệu trong ES6)):
console.log(typeof true); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof function () {}); // function
Như bạn có thể thấy các đối tượng, mảng và giá trị null
đều là các đối tượng được xem xét ( null
là một tham chiếu đến một đối tượng không tồn tại). Các chức năng được phân biệt bởi vì chúng là một loại đối tượng có thể gọi được đặc biệt . Tuy nhiên họ vẫn là đối tượng.
Mặt khác các literals true
, 0
, ""
và undefined
không phải là đối tượng. Chúng là các giá trị nguyên thủy trong JavaScript. Tuy nhiên dữ liệu boolean, số và chuỗi cũng có nhà thầu Boolean
, Number
và String
tương ứng mà quấn nguyên thủy của mình để cung cấp tính năng bổ sung:
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
Như bạn có thể nhìn thấy khi giá trị nguyên thủy được gói trong Boolean
, Number
và String
nhà xây dựng tương ứng họ trở thành đối tượng. Các instanceof
nhà điều hành chỉ hoạt động cho các đối tượng (đó là lý do nó sẽ trả về false
cho các giá trị nguyên thủy):
console.log(true instanceof Boolean); // false
console.log(0 instanceof Number); // false
console.log("" instanceof String); // false
console.log(new Boolean(true) instanceof Boolean); // true
console.log(new Number(0) instanceof Number); // true
console.log(new String("") instanceof String); // true
Như bạn có thể thấy cả hai typeof
và instanceof
không đủ để kiểm tra xem một giá trị là boolean, một số hay một chuỗi - typeof
chỉ hoạt động cho các booleans, số và chuỗi nguyên thủy; và instanceof
không hoạt động cho booleans nguyên thủy, số và chuỗi.
May mắn thay, có một giải pháp đơn giản cho vấn đề này. Việc triển khai mặc định toString
(nghĩa là được xác định rõ ràng trên Object.prototype.toString
) trả về thuộc tính bên trong [[Class]]
của cả các giá trị và đối tượng nguyên thủy:
function classOf(value) {
return Object.prototype.toString.call(value);
}
console.log(classOf(true)); // [object Boolean]
console.log(classOf(0)); // [object Number]
console.log(classOf("")); // [object String]
console.log(classOf(new Boolean(true))); // [object Boolean]
console.log(classOf(new Number(0))); // [object Number]
console.log(classOf(new String(""))); // [object String]
[[Class]]
Thuộc tính bên trong của một giá trị hữu ích hơn nhiều so với typeof
giá trị. Chúng ta có thể sử dụng Object.prototype.toString
để tạo phiên bản typeof
toán tử (hữu ích hơn) của riêng mình như sau:
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(typeOf(true)); // Boolean
console.log(typeOf(0)); // Number
console.log(typeOf("")); // String
console.log(typeOf(new Boolean(true))); // Boolean
console.log(typeOf(new Number(0))); // Number
console.log(typeOf(new String(""))); // String
Hy vọng bài viết này đã giúp. Để biết thêm về sự khác biệt giữa các đối tượng nguyên thủy và các đối tượng được bọc, hãy đọc bài đăng trên blog sau: Cuộc sống bí mật của người nguyên thủy JavaScript