在JavaScript中,所有东西都是对象(或者至少可以被视为对象),除了基本类型(布尔值、null、数字、字符串和undefined值(以及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
正如你所看到的,对象、数组和null值都被认为是对象(null是对一个不存在的对象的引用)。函数的区别在于它们是一种特殊类型的可调用对象。然而,它们仍然是物体。
另一方面,字面量true, 0, ""和undefined不是对象。它们是JavaScript中的原始值。然而,布尔值,数字和字符串也有构造函数Boolean, Number和String,它们分别包装各自的原语以提供额外的功能:
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
正如你所看到的,当原始值分别被包装在Boolean、Number和String构造函数中时,它们就变成了对象。instanceof操作符只对对象有效(这就是为什么它对原始值返回false):
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
正如你所看到的,typeof和instanceof都不足以测试一个值是布尔值、数字还是字符串——typeof只适用于基本布尔值、数字和字符串;instanceof对原始布尔值,数字和字符串无效。
幸运的是,这个问题有一个简单的解决方案。toString的默认实现(即在Object.prototype.toString上原生定义)返回原语值和对象的内部[[Class]]属性:
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]]属性比值的类型有用得多。我们可以使用Object.prototype.toString创建我们自己的(更有用的)typeof操作符版本,如下所示:
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
希望这篇文章能有所帮助。要了解更多关于原语和包装对象之间的区别,请阅读以下博客文章:JavaScript原语的秘密生活