为什么instanceof对某些文字返回false?


284
"foo" instanceof String //=> false
"foo" instanceof Object //=> false
true instanceof Boolean //=> false
true instanceof Object //=> false
false instanceof Boolean //=> false
false instanceof Object //=> false

// the tests against Object really don't make sense

数组文字和对象文字匹配...

[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true

为什么不全部?或者,为什么不是所有人都不呢?
而且,它们是什么实例呢?

在FF3,IE7,Opera和Chrome中相同。因此,至少是一致的。


错过了几个。

12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true

Answers:


424

与从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都会做其他事情。


5
每天都有讨厌JavaScript的新理由是美好的一天。我知道应该早就该了,但是我感谢你的这篇文章。
toniedzwiedz 2012年

57
您的术语是错误的。单词“ literal”是指无需使用构造函数即可创建数据的语法。它不引用结果数据。文字语法可用于创建对象和非对象。正确的术语是“原始”,指的是非对象数据。一些数据同时具有原始表示和对象表示。字符串是那些数据类型之一。
灰色状态将

14
仅供参考,您可以创建不带文字语法的原语。(new String()).valueOf();
灰色状态将于

11
请注意,这typeof foo === 'string'还不够:请参阅axkibe的答案。
布莱恩·拉森

1
在附加,typeof new String('')回报"object"
transang

105

我用:

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

因为在JavaScript中,字符串可以是文字或对象。


28
我发现东西有点不足。function isString(s) { return s.constructor === String; }适用于文字和字符串对象(至少在V8中适用)
axkibe 2011年

7
一定喜欢JavaScript。
德里克·朕会功夫

2
尽可能使用jQuery.type(s)==='string'(api.jquery.com/jquery.type),jQuery.isArray(),jQuery.isFunction(),jQuery.isNumeric()。
伊万·萨米金

1
@axkibe正确时,其性能不如typeof
Qix-蒙尼卡(Monica)

您可以使用typeof“?” == String.name.toLowerCase()[但是为什么[[] instanceof Array?]
QuentinUK

62

在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是对不存在的对象的引用)。函数之所以与众不同,是因为它们是可调用对象的一种特殊类型。但是它们仍然是对象。

在另一方面,文字true0""undefined不是对象。它们是JavaScript中的原始值。但是,布尔值,数字和字符串也具有构造函数BooleanNumber并且String分别包装它们各自的基元以提供附加功能:

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基元的秘密生活


6
+1,同样null也是一个原始值(只有typeof操作员感到困惑)
Bergi

33

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

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

18
请注意,在测试变量时,该技术在某些情况下可能会失败。在上一个示例的前面String和之前Boolean,有一个对当前窗口的隐式引用,因此,如果您要测试constructor在另一个窗口(如弹出窗口或框架)中创建的字符串变量的属性,它将等于simple String,而是等于thatOtherWindowsName.String
Michael Mathews 2010年

并且instanceof不能处理此问题并返回适当的布尔结果吗?
克里斯·诺

5
如果您传递了String的后代,则此操作将失败。
布莱恩·拉尔森

1
@MichaelMathews:此方法可以补救:Object.prototype.toString.call('foo') === '[object String]'
rvighne 2014年

@BryanLarsen和@MichaelMathews使用时有任何问题d.constructor == String吗?例如,使用宽松的相等运算符。
dotnetCarpenter

7
 typeof(text) === 'string' || text instanceof String; 

您可以使用它,这对于两种情况都适用

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

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


3

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

换句话说,如果ObjObj instanceof Callable不是对象时,instanceof将短路false直接。


1

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

Object.getPrototypeOf('test') === String.prototype    //true
Object.getPrototypeOf(1) === String.prototype         //false

-1

https://www.npmjs.com/package/typeof

返回instanceof(构造函数名称)的字符串表示形式

function instanceOf(object) {
  var type = typeof object

  if (type === 'undefined') {
    return 'undefined'
  }

  if (object) {
    type = object.constructor.name
  } else if (type === 'object') {
    type = Object.prototype.toString.call(object).slice(8, -1)
  }

  return type.toLowerCase()
}

instanceOf(false)                  // "boolean"
instanceOf(new Promise(() => {}))  // "promise"
instanceOf(null)                   // "null"
instanceOf(undefined)              // "undefined"
instanceOf(1)                      // "number"
instanceOf(() => {})               // "function"
instanceOf([])                     // "array"

-2

对我而言,

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

因此"str" istanceof String应返回,true因为istanceof的工作方式如下:

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

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

#1错误

我发现这是由__proto__非标准属性引起的,因此请使用标准属性:Object.getPrototypeOf

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

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


2
#1是正确的,但这归因于属性访问器,该访问器将原始值包装到其各自的对象类型,类似于Object("str").__proto__Object("str") instanceof String
乔纳森·洛诺夫斯基

@JonathanLonowski感谢您指出这一点。我不知道
mko

-8

或者,您可以像这样使自己的功能:

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

用法:

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

这些都应返回true。


14
我看到评估。邪恶。
Aaria Carter-Weir 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.