为什么一些文字的 instanceof 返回 false?

"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 中都是一样的,所以,至少它是一致的。

124591 次浏览

原语是一种不同于Javascript中创建的对象的类型。从Mozilla API文档:

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)

我找不到任何方法来构造原始类型的代码,也许这是不可能的。这可能就是为什么人们使用typeof "foo" === "string"而不是instanceof

记住这些事情的一个简单方法是问自己“我想知道什么是理智的和容易学的”?不管答案是什么,Javascript做的是另一件事。

你可以使用构造函数属性:

'foo'.constructor == String // returns true
true.constructor == Boolean // returns true

或者你可以像这样创建你自己的函数:

function isInstanceOf(obj, clazz){
return (obj instanceof eval("("+clazz+")")) || (typeof obj == clazz.toLowerCase());
};

用法:

isInstanceOf('','String');
isInstanceOf(new String(), 'String');

这些都应该返回true。

我使用:

function isString(s) {
return typeof(s) === 'string' || s instanceof String;
}

因为在JavaScript中字符串可以是字面量也可以是对象。

在JavaScript中,所有东西都是对象(或者至少可以被视为对象),除了原语(布尔值、空值、数字、字符串和值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是对一个不存在的对象的引用)。函数是有区别的,因为它们是特殊类型的可调用的对象。然而,它们仍然是物体。

另一方面,字面量true0""undefined不是对象。它们是JavaScript中的原始值。然而,布尔值、数字和字符串也分别有构造函数BooleanNumberString,它们分别包装了它们各自的原语以提供额外的功能:

console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0));     // object
console.log(typeof new String(""));    // object

正如你所看到的,当基元值分别被包装在BooleanNumberString构造函数中时,它们就变成了对象。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

正如你所看到的,typeofinstanceof都不足以测试一个值是布尔值、数字还是字符串——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

希望这篇文章能有所帮助。要了解更多关于原语和包装对象之间的区别,请阅读以下博客文章:JavaScript原语的秘密生活

对我造成的困惑

"str".__proto__ // #1
=> String

所以"str" istanceof String应该返回true,因为istanceof的工作原理如下:

"str".__proto__ == String.prototype // #2
=> true

表达式# 1#2的结果相互冲突,因此应该有一个是错误的。

第一条是错的

我发现它是由__proto__是非标准属性引起的,所以使用标准属性:Object.getPrototypeOf

Object.getPrototypeOf("str") // #3
=> TypeError: Object.getPrototypeOf called on non-object

现在表达式#2# 3之间没有混淆了

我相信我已经想出了一个可行的解决方案:

Object.getPrototypeOf('test') === String.prototype    //true
Object.getPrototypeOf(1) === String.prototype         //false
 typeof(text) === 'string' || text instanceof String;

你可以用这个,这两种情况都适用

  1. var text="foo"; // typeof将工作

  2. String text= new String("foo"); // instanceof将工作

这在ECMAScript规范7.3.19步骤3: If Type(O) is not Object, return false.中定义

换句话说,如果Obj instanceof Callable中的Obj不是一个对象,instanceof将直接短路到false

基本包装器类型是在字符串、数字或布尔值出现时在幕后自动创建的引用类型 是阅读。例如:

var name = "foo";
var firstChar = name.charAt(0);
console.log(firstChar);

这是幕后发生的事情:

// what the JavaScript engine does
var name = "foo";
var temp = new String(name);
var firstChar = temp.charAt(0);
temp = null;
console.log(firstChar);

因为第二行像对象一样使用字符串(原语), JavaScript引擎创建一个String实例,这样charAt(0)就会 工作。String对象在被销毁之前只存在于一条语句中 检查 < / p > 运算符操作符返回false,因为临时对象为 仅在读取值时创建。因为instanceof实际上并不读取 任何东西,没有临时对象被创建,它告诉我们-values没有被创建 基本包装器类型的实例。您可以创建原始包装器 类型手动< / p >