"instanceof" of a String object vs that of "string" literals String对象的"instanceof"与"string"字面值的"instanceof"的区别
"instanceof" of a String object vs that of "string" literals String对象的"instanceof"与"string"字面值的"instanceof"的区别
"foo" instanceof String //=> false
"foo" instanceof Object //=> false
true instanceof Boolean //=> false
true instanceof Object //=> false
false instanceof Boolean //=> false
false instanceof Object //=> false
12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true
// the tests against Object really don't make sense
数组字面量和对象字面量匹配...
[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true
为什么不是全部都匹配呢?或者说,为什么它们不全部都不匹配呢?
然后,它们是什么的实例呢?
在FF3、IE7、Opera和Chrome中都是一样的。所以,至少是一致的。
在JavaScript中,除了原始值(布尔值、null、数字、字符串和undefined)之外,一切都是对象(或者至少可以被视为对象)。如下代码示例所示,对象、数组和null值都被视为对象,而函数被视为一种特殊类型的可调用对象:
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
需要注意的是,虽然函数被认为是一种特殊类型的对象,但它们仍然是对象。另一方面,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。
在Javascript中,原始类型与在Javascript中创建的对象是不同的类型。从Mozilla API文档中可以看到,可以使用instanceof
操作符来判断一个对象是否是某个特定类型的实例。例如,下面的代码可以判断一个对象是否是String类型的实例:
var color1 = new String("green"); color1 instanceof String; // 返回true var color2 = "coral"; color2 instanceof String; // 返回false(color2不是一个String对象)
然而,对于原始类型的判断,由于无法使用代码构造原始类型的实例,所以无法使用instanceof
操作符。这可能就是为什么人们使用typeof "foo" === "string"
而不是instanceof
的原因。
另一个使用typeof
而不是instanceof
的原因是,typeof
测试可以在来自其他框架或窗口的字符串上仍然有效,或者在String
构造函数被重写的情况下仍然有效。
另外,可以使用+' '
将String对象转换为字符串字面量的形式,例如(new String('green') + '') instanceof String
将返回false。
需要注意的是,typeof foo === 'string'
并不足够,可以使用Object.prototype.toString.call(foo)
来进行更准确的判断。
总之,Javascript在处理字符串字面量与String对象时存在一些不一致和令人困惑的地方。原始类型与对象表示之间的区别是其中一个原因,另一个原因是instanceof
操作符无法对原始类型进行判断。这可能是Javascript设计上的一些不一致之处。