在 JavaScript 中,一切都是对象(或者至少可以被视为对象),除了 primitives(布尔值、空值、数字、字符串和值 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 是对不存在的对象的引用)。函数之所以与众不同,是因为它们是一种特殊类型的 callable 对象。但是它们仍然是对象。
另一方面,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]] 属性比typeof 值有用得多。我们可以使用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
希望这篇文章有所帮助。要了解有关原语和包装对象之间差异的更多信息,请阅读以下博客文章:The Secret Life of JavaScript Primitives