web-dev-qa-db-ja.com

いくつかのリテラルで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

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

配列リテラルとオブジェクトリテラルが一致...

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

なぜそれらのすべてではないのですか?または、なぜそれらすべてnotではないのですか?
そして、そのインスタンスは何ですか?

FF3、IE7、Opera、Chromeでも同じです。したがって、少なくとも一貫性があります。


いくつか逃した。

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

プリミティブは、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)

コードでプリミティブ型を構築する方法を見つけることができません。おそらく不可能です。これはおそらく、人々がinstanceofの代わりにtypeof "foo" === "string"を使用する理由です。

このようなことを覚える簡単な方法は、「正気で習得しやすいものは何だろう」と自問することです。答えが何であれ、Javascriptは他のことを行います。

385
John Millikin

私が使う:

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

JavaScriptでは、文字列はリテラルまたはオブジェクトにできるためです。

93
axkibe

JavaScriptでは、 primitives (ブール値、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は存在しないオブジェクトへの参照です)。関数は、特別なタイプのcallableオブジェクトであるため区別されます。ただし、それらはまだオブジェクトです。

一方、リテラル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

プリミティブ値がBooleanNumber、および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

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の秘密の生活プリミティブ

56
Aadit M Shah

コンストラクタープロパティを使用できます。

'foo'.constructor == String // returns true
true.constructor == Boolean // returns true
31
user144049
 typeof(text) === 'string' || text instanceof String; 

あなたはこれを使用することができます、それは両方のケースで動作します

  1. var text="foo"; // typeofは機能します

  2. String text= new String("foo"); // instanceofは機能します

6
saurabhgoyal795

私は実行可能な解決策を考え出したと信じています。

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

これは、ECMAScript仕様で定義されています セクション7.3.19ステップIf Type(O) is not Object, return false.

言い換えれば、Obj instanceof CallableObjがオブジェクトでない場合、instanceoffalseに直接短絡します。

1
HKTonyLee