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

IT技术 javascript literals instanceof
2021-01-15 17:02:28
"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 中也是如此。所以,至少它是一致的。

6个回答

原语是一种不同于在 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 会做另一件事。

此外,typeof new String('')返回"object"
2021-03-15 17:02:28
你的术语是错误的。“字面量”一词是指无需使用构造函数即可创建数据的语法。它不涉及结果数据。文字语法可用于创建对象和非对象。正确的术语是“原语”,它指的是非对象数据。一些数据同时具有原始和对象表示。字符串是这些类型的数据之一。
2021-03-24 17:02:28
请注意,这typeof foo === 'string'还不够:请参阅 axkibe 的回答。
2021-03-31 17:02:28
每天都有新的理由来讨厌 JavaScript 是美好的一天。我知道它早就应该了,但我感谢你的这篇文章。
2021-04-05 17:02:28
仅供参考,您可以创建没有文字语法的原语。 (new String()).valueOf();
2021-04-10 17:02:28

我用:

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

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

@axkibe 虽然你是对的,但它的性能不如typeof.
2021-03-13 17:02:28
布尔值也存在同样的问题:true instanceof Boolean => false然而typeof true => boolean......甚至是什么。stackoverflow.com/a/4745303/362042
2021-03-24 17:02:28
顺便说一句,我发现了一些简短的东西。function isString(s) { return s.constructor === String; }适用于文字和字符串对象(至少在 V8 中)
2021-03-25 17:02:28
您可以使用 typeof "?" == String.name.toLowerCase() [但为什么是 [] instanceof Array ?]
2021-04-02 17:02:28
尽可能使用 jQuery.type(s) === 'string' ( api.jquery.com/jquery.type )、jQuery.isArray()、jQuery.isFunction()、jQuery.isNumeric()。
2021-04-07 17:02:28

在 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 中的原始值。然而,布尔值、数字和字符串也有构造函数Boolean,NumberString分别包装它们各自的原语以提供附加功能:

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

+1,虽然null也是原始值(只有typeof运算符令人困惑)
2021-03-31 17:02:28

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

'foo'.constructor == String // returns true
true.constructor == Boolean // returns true
请注意,在测试变量时,此技术在某些情况下可能会失败。有在前面的当前窗口的隐式引用String,并Boolean在上面的例子中,因此,如果要测试的constructor在另一个窗口中创建了一个字符串变量的属性(如弹出或帧),它会等于简单地String,它会等于thatOtherWindowsName.String
2021-03-14 17:02:28
并且 instanceof 不处理这个并返回适当的布尔结果吗?
2021-03-18 17:02:28
@MichaelMathews:这可以解决以下问题: Object.prototype.toString.call('foo') === '[object String]'
2021-03-29 17:02:28
如果您传递了 String 的后代,这将失败。
2021-04-06 17:02:28
@BryanLarsen 和 @MichaelMathews 使用有什么问题d.constructor == String吗?例如,使用松散的相等运算符。
2021-04-06 17:02:28
 typeof(text) === 'string' || text instanceof String; 

你可以使用它,它适用于两种情况

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

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