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 ( nulllà 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à undefinedkhô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, Numbervà Stringtươ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, Numbervà Stringnhà xây dựng tương ứng họ trở thành đối tượng. Các instanceofnhà điều hành chỉ hoạt động cho các đối tượng (đó là lý do nó sẽ trả về falsecho 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 typeofvà instanceofkhông đủ để kiểm tra xem một giá trị là boolean, một số hay một chuỗi - typeofchỉ hoạt động cho các booleans, số và chuỗi nguyên thủy; và instanceofkhô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 typeofgiá trị. Chúng ta có thể sử dụng Object.prototype.toStringđể tạo phiên bản typeoftoá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