JSオブジェクトのタイプをチェックする最も正確な方法は?


137

typeofオペレータは、実際のオブジェクトの本当の種類を見つけるために私たちを助けていません。

私はすでに次のコードを見ました:

Object.prototype.toString.apply(t)  

質問:

それはオブジェクトのタイプをチェックする最も正確な方法ですか?





3
最も正確な方法は...型をテストしないことです。なぜ型が必要なのですか?
hugomg 2011年

Object.prototype.toString.call / Object.prototype.toString.apply
xgqfrms

回答:


190

JavaScript仕様では、オブジェクトのクラスを決定するための適切な方法が1つだけ提供されています。

Object.prototype.toString.call(t);

http://bonsaiden.github.com/JavaScript-Garden/#types


5
特定のタイプを探している場合は、おそらく次のように何かを実行する必要Object.prototype.toString.call(new FormData()) === "[object FormData]"があります。の代わりに使用slice(8, -1)して戻ることもできますFormData[object FormData]
Chris Marisic 14

4
使用の間に何らかの違いがあるObject.prototypeとは{}
GetFree

3
多分これは何年にもわたって変化しましたObject.prototype.toString.call(new MyCustomObject())[object Object]new MyCustomObject() instanceOf MyCustomObject returns trueそれが私が望んでいたものであるのに戻ります(Chrome 54.0.2840.99 m)
Maslow

@Maslow、あなたが提起したのと同じ問題に遭遇しました。オンラインでいくつかのドキュメントを調べた後、結局を使用しましたnew MyCustomObject().constructor === MyCustomObject
solstice333

3
それは、なぜ彼らがこのコードをより便利な方法でラップしなかったのか、または追加のオペレーターがこれにコンパイルすることを許可しなかったのかという疑問を投げかけます。私はあなたがメッセンジャーにすぎないことを知っていますが、率直に言ってそれはひどいです。
アンドリューS

60

これObject.prototype.toStringは良い方法ですが、そのパフォーマンスは最悪です。

http://jsperf.com/check-js-type

jsタイプのパフォーマンスをチェックする

使用するtypeofいくつかの基本的な問題(文字列、数値、ブール...)と使用を解決するためにObject.prototype.toString(アレイ、日付、正規表現のような)複雑な何かを解決するために。

これが私の解決策です:

var type = (function(global) {
    var cache = {};
    return function(obj) {
        var key;
        return obj === null ? 'null' // null
            : obj === global ? 'global' // window in browser or global in nodejs
            : (key = typeof obj) !== 'object' ? key // basic: string, boolean, number, undefined, function
            : obj.nodeType ? 'object' // DOM element
            : cache[key = ({}).toString.call(obj)] // cached. date, regexp, error, object, array, math
            || (cache[key] = key.slice(8, -1).toLowerCase()); // get XXXX from [object XXXX], and cache it
    };
}(this));

使用:

type(function(){}); // -> "function"
type([1, 2, 3]); // -> "array"
type(new Date()); // -> "date"
type({}); // -> "object"

jsPerfでのこのテストは正確ではありません。これらのテストは等しくありません(同じことをテストします)。たとえば、typeof []は "object"を返し、typeof {}も "object"を返しますが、一方がオブジェクト配列で、もう一方がオブジェクトObjectです。このテストには他にも多くの問題があります... jsPerfを見るときは、テストがAppleとAppleを比較していることに注意してください。
kmatheny 2012

あなたのtype機能は良いですが、他のいくつかのtype機能と比較してどのように機能するか見てください。http://jsperf.com/code-type-test-a-test
Progo

18
これらのパフォーマンスメトリックは、常識的に調整する必要があります。確かに、prototype.toStringは他のものよりも桁違いに遅いですが、大まかな計画では、呼び出しごとに平均で数百ナノ秒かかります。この呼び出しが非常に頻繁に実行されるクリティカルパスで使用されていない限り、これはおそらく無害です。1マイクロ秒速く終了するコードよりも、単純なコードが欲しいです。
デビッド

({}).toString.call(obj)Object.prototype.toString jsperf.com/object-check-test77
timaschew

素晴らしい解決策。私はあなたの機能を私のlibに借用します:)
Dong Nguyen

19

正解は正解ですが、私が構築するほとんどのプロジェクトでこの小さなユーティリティを定義するのが好きです。

var types = {
   'get': function(prop) {
      return Object.prototype.toString.call(prop);
   },
   'null': '[object Null]',
   'object': '[object Object]',
   'array': '[object Array]',
   'string': '[object String]',
   'boolean': '[object Boolean]',
   'number': '[object Number]',
   'date': '[object Date]',
}

このように使用されます:

if(types.get(prop) == types.number) {

}

角度を使用している場合は、きれいに注入することもできます。

angular.constant('types', types);

11
var o = ...
var proto =  Object.getPrototypeOf(o);
proto === SomeThing;

オブジェクトに必要なプロトタイプのハンドルを保持し、それと比較します。

例えば

var o = "someString";
var proto =  Object.getPrototypeOf(o);
proto === String.prototype; // true

これは言うよりも良い/違うのo instanceof String; //trueですか?
Jamie Treworgy、2011年

@jamietreので"foo" instanceof String休憩
レイノス

OK、「typeof(o)=== 'object' && o instanceof SomeObject」。文字列のテストは簡単です。何をテストするのかを事前に知る必要があるという基本的な問題を解決せずに、余分な作業のように見えます。
Jamie Treworgy、2011年

申し訳ありませんが、そのコードスニペットは意味がありませんが、私はあなたが文字列をテストしている場合は、使用し、私が何を意味するか知っていると思うtypeof(x)==='string'の代わりに。
Jamie Treworgy、2011年

ところで、Object.getPrototypeOf(true)(true).constructor戻る場所で失敗しますBoolean
katspaugh、2011年

5

ここに示されているソリューションのほとんどは、過度に設計されていることに悩まされていると私は主張します。おそらく、値が型であるかどうかを確認する最も簡単な方法は、[object Object]その.constructorプロパティをチェックすることです。

function isObject (a) { return a != null && a.constructor === Object; }

または、矢印機能を使用してさらに短くする:

const isObject = a => a != null && a.constructor === Object;

a != nullが渡される可能性があり、nullまたundefinedこれらのどちらからもコンストラクタープロパティを抽出できないため、この部分が必要です。

これは、以下を介して作成された任意のオブジェクトで機能します。

  • Objectコンストラクタ
  • リテラル {}

それのもう一つのきちんとした機能は、それを利用するカスタムクラスのための正しいレポートを与える能力ですSymbol.toStringTag。例えば:

class MimicObject {
  get [Symbol.toStringTag]() {
    return 'Object';
  }
}

ここでの問題は、そのObject.prototype.toStringインスタンスを呼び出すと、誤ったレポート[object Object]が返されることです。

let fakeObj = new MimicObject();
Object.prototype.toString.call(fakeObj); // -> [object Object]

しかし、コンストラクタに対してチェックすると、正しい結果が得られます。

let fakeObj = new MimicObject();
fakeObj.constructor === Object; // -> false

4

オブジェクトのREALタイプ(ネイティブオブジェクトまたはDataType名(String、Date、Number、.. etcなど)とオブジェクトのREALタイプ(カスタムオブジェクトも含む)の両方を含む)を見つける最良の方法は、オブジェクトプロトタイプのコンストラクタのnameプロパティ:

ネイティブタイプEx1:

var string1 = "Test";
console.log(string1.__proto__.constructor.name);

表示:

String

例2:

var array1 = [];
console.log(array1.__proto__.constructor.name);

表示:

Array

カスタムクラス:

function CustomClass(){
  console.log("Custom Class Object Created!");
}
var custom1 = new CustomClass();

console.log(custom1.__proto__.constructor.name);

表示:

CustomClass

オブジェクトがどちらかである場合、これは失敗しましたnullundefined
ジュリアンナイト

2

古い質問です。変換する必要はありません。この機能を参照してください:

function getType( oObj )
{
    if( typeof oObj === "object" )
    {
          return ( oObj === null )?'Null':
          // Check if it is an alien object, for example created as {world:'hello'}
          ( typeof oObj.constructor !== "function" )?'Object':
          // else return object name (string)
          oObj.constructor.name;              
    }   

    // Test simple types (not constructed types)
    return ( typeof oObj === "boolean")?'Boolean':
           ( typeof oObj === "number")?'Number':
           ( typeof oObj === "string")?'String':
           ( typeof oObj === "function")?'Function':false;

}; 

例:

function MyObject() {}; // Just for example

console.log( getType( new String( "hello ") )); // String
console.log( getType( new Function() );         // Function
console.log( getType( {} ));                    // Object
console.log( getType( [] ));                    // Array
console.log( getType( new MyObject() ));        // MyObject

var bTest = false,
    uAny,  // Is undefined
    fTest  function() {};

 // Non constructed standard types
console.log( getType( bTest ));                 // Boolean
console.log( getType( 1.00 ));                  // Number
console.log( getType( 2000 ));                  // Number
console.log( getType( 'hello' ));               // String
console.log( getType( "hello" ));               // String
console.log( getType( fTest ));                 // Function
console.log( getType( uAny ));                  // false, cannot produce
                                                // a string

低コストでシンプル。


falseテストオブジェクトがnullorであるかどうかを返しますundefined
Julian Knight

またはtrueまたはfalse
Julian Knight

@JulianKnight falseはnullまたは未定義で問題ありませんが、何も役に立ちません。だからポイントは何ですか?
コードビート

あなたの例は矛盾したデータを返します。結果にはデータ型とその他の結果がありますfalse。これは質問への回答にどのように役立ちますか?
ジュリアンナイト

1
@JulianKnight変更を参照してください。結果として未定義または「未定義」を希望する場合は、必要に応じて最後のfalseを置き換えることができます。
コードビート

0

上記の正解に触発された小さな型チェックユーティリティをまとめました。

thetypeof = function(name) {
        let obj = {};
        obj.object = 'object Object'
        obj.array = 'object Array'
        obj.string = 'object String'
        obj.boolean = 'object Boolean'
        obj.number = 'object Number'
        obj.type = Object.prototype.toString.call(name).slice(1, -1)
        obj.name = Object.prototype.toString.call(name).slice(8, -1)
        obj.is = (ofType) => {
            ofType = ofType.toLowerCase();
            return (obj.type === obj[ofType])? true: false
        }
        obj.isnt = (ofType) => {
            ofType = ofType.toLowerCase();
            return (obj.type !== obj[ofType])? true: false
        }
        obj.error = (ofType) => {
            throw new TypeError(`The type of ${name} is ${obj.name}: `
            +`it should be of type ${ofType}`)
        }
        return obj;
    };

例:

if (thetypeof(prop).isnt('String')) thetypeof(prop).error('String')
if (thetypeof(prop).is('Number')) // do something

nullor undefinedまたはtrueorのオブジェクトに対しては機能しないようですfalse
Julian Knight
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.