JavaScript変数の型を取得するより良い方法?


260

JSで変数の型を取得するより良い方法はありtypeofますか?あなたがするときそれはうまく働きます:

> typeof 1
"number"
> typeof "hello"
"string"

しかし、それを試しても役に立たない:

> typeof [1,2]
"object"
>r = new RegExp(/./)
/./
> typeof r
"function"

私は知っていinstanceofますが、これには事前にタイプを知っている必要があります。

> [1,2] instanceof Array
true
> r instanceof RegExp
true

もっと良い方法はありますか?


1
typeof new RegExp(/./); // "function"
参考


警告:JSを縮小し、typescriptクラスなどの「カスタムオブジェクト」を使用している場合、以下の回答の一部nは、期待される元の名前ではなく、難読化された関数名を提供することになります。たとえば、予想されるフルネームの代わりにconstructor.nameあなたnに与えるかもしれません
Simon_Weaver

回答:


221

Angus Crollは最近、これについて興味深いブログ投稿を書いています-

http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

彼はさまざまなメソッドの長所と短所を調べ、新しいメソッド「toType」を定義します-

var toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

3
ここで興味深い注意点があります。これは、「ホスト」オブジェクトが関数に渡される場所で壊れる可能性があります。ActiveXObjectたとえば、Internet Explorer インスタンス。
Andy E

独自のオブジェクトタイプ(プロトタイプの継承)を作成した場合、「オブジェクト」よりも具体的な値を返すにはどうすればよいでしょうか。これもここで問題として提起されましたが、対処されませんでした。
EleventyOne 2013

1
タイプの名前に:または_が含まれている場合、この正規表現を次のように拡張できますmatch(/\s([a-z,_,:,A-Z]+)/)
masi

6
正規表現には、などの数値も含める必要がありますUint8Array。代わりに、match(/\s([^\]]+)/)何を処理する必要があるより一般的なものを検討してください。
Lily Finley

2
\w代わりに単語の演算子を使用することをお勧めします…
kaiser

51

を使用してみてくださいconstructor.name

[].constructor.name
new RegExp().constructor.name

すべてのJavaScriptと同様に、誰かが最終的にこれが何らかの形で悪であることを常に指摘するため、これはこれをかなりうまくカバーする回答へのリンクです。

代替は使用することです Object.prototype.toString.call

Object.prototype.toString.call([])
Object.prototype.toString.call(/./)

10
nameECMAScriptの拡張機能であり、すべてのブラウザで機能するわけではありません。
アンディE

16
JavaScriptで行われたすべてが何らかの形で悪であるという疑いを確認したため、投票に回答しました。
liljoshu 2015年

1
EVIL:コードを縮小化constructor.nameしているn場合、期待するオブジェクト名ではなく、次のようなものになる可能性があります。そのため、特に本番環境でのみ縮小する場合は注意してください。
Simon_Weaver 2017年

nullそしてundefined残念ながら、コンストラクタを持っていません。
Andrew Grimm

JavaScript自体は悪です。そしてばかげた。この質問に良い答えがないという事実は、それの生きた証拠です。
user2173353 2018年

38

適度に良いタイプのキャプチャ機能は、YUI3で使用されるものです

var TYPES = {
    'undefined'        : 'undefined',
    'number'           : 'number',
    'boolean'          : 'boolean',
    'string'           : 'string',
    '[object Function]': 'function',
    '[object RegExp]'  : 'regexp',
    '[object Array]'   : 'array',
    '[object Date]'    : 'date',
    '[object Error]'   : 'error'
},
TOSTRING = Object.prototype.toString;

function type(o) {
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
};

これはJavaScriptによって提供される多くのプリミティブをキャプチャしますが、TYPESオブジェクトを変更することでいつでもプリミティブを追加できます。注意typeof HTMLElementCollectionSafariで報告されますfunctionが、タイプ(HTMLElementCollection)が返されますobject


31

次の関数が役立つ場合があります。

function typeOf(obj) {
  return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}

またはES7で(さらに改善する場合はコメント)

function typeOf(obj) {
  const { toString } = Object.prototype;
  const stringified = obj::toString();
  const type = stringified.split(' ')[1].slice(0, -1);

  return type.toLowerCase();
}

結果:

typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
typeOf(new Error) //error
typeOf(Promise.resolve()) //promise
typeOf(function *() {}) //generatorfunction
typeOf(new WeakMap()) //weakmap
typeOf(new Map()) //map

エラー、プロミス、ジェネレーター関数を通知してくれた@johnreesに感謝


これをありがとう。また、日付オブジェクトのために動作します:typeOf(new Date())
ジェームズ・アーウィン

ああ、私はそれについて忘れていました-ありがとう、それは今含まれています。
Vix

1
そしてtypeOf(Promise.resolve())//promise typeOf(function *() {})//generatorfunction
ジョンリーズ

私はこの答えをtypescriptで機能させることができません。エラーが発生する:[ts] Cannot redeclare block-scoped variable 'toString'
DauleDK

TypeScriptについては不明です。ES7バージョンを試しましたか?toStringが明示的に宣言されていないことが原因である可能性がありますか?
Vix

15

また、ipr101から少し例を変更できます

Object.prototype.toType = function() {
  return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

として呼び出す

"aaa".toType(); // 'string'

6
子供を思い出してください。JavaScriptベースのオブジェクトを操作すると、互換性やその他の奇妙な問題が発生する可能性があります。ライブラリと大規模プロジェクトの両方でこれを慎重に使用してください!
Alexander Craggs

9

一行関数:

function type(obj) {
    return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"$1").toLowerCase()
}

これは同じ結果になります jQuery.type()


3

Object.prototype.toString任意のオブジェクトに適用できます。

var toString = Object.prototype.toString;

console.log(toString.call([]));
//-> [object Array]

console.log(toString.call(/reg/g));
//-> [object RegExp]

console.log(toString.call({}));
//-> [object Object]

これは、IEを除いて、すべてのブラウザで適切に機能し[object Object]ます。別のウィンドウから取得した変数でこれを呼び出すと、単に吐き出されます。


1
@Xeon IEに対する憎しみは少なすぎると思います。IE9は、以前のバージョンよりもはるかに優れたブラウザです。
Aillyn、2011

4
@pessimopoppotamusがブラウザをIE9に更新する人は誰もIEを使用しません。
Alex Turpin

1
IE 9は正しい方向への一歩です。IE10はかなり見栄えがします。ちなみに、私が言及したバグはIE 9のリグレッションでした-IE 8で修正されました
Andy E

3

2¢!実際、私がこれをここに投げ出す理由の1つは、長い答えのリストにもかかわらず、もう少しall in oneタイプソリューションを提供し、それをさらに含めるために拡張する方法について将来のフィードバックを得るためreal typesです。

前述のように、次の解決策を使用して、ここにあるいくつかの解決策を組み合わせ、jQueryで定義されたオブジェクトの値を返すための修正を組み込みます(可能な場合)。また、メソッドをネイティブObjectプロトタイプに追加します。他の拡張機能に干渉する可能性があるため、多くの場合タブーはタブーですが、それはに任せています。この方法が気に入らない場合は、ベース関数を好きな場所にコピーし、のすべての変数を引数パラメーター(arguments [0]など)に置き換えてください。jQueryuser bewarethis

;(function() {  //  Object.realType
    function realType(toLower) {
        var r = typeof this;
        try {
            if (window.hasOwnProperty('jQuery') && this.constructor && this.constructor == jQuery) r = 'jQuery';
            else r = this.constructor && this.constructor.name ? this.constructor.name : Object.prototype.toString.call(this).slice(8, -1);
        }
        catch(e) { if (this['toString']) r = this.toString().slice(8, -1); }
        return !toLower ? r : r.toLowerCase();
    }
    Object['defineProperty'] && !Object.prototype.hasOwnProperty('realType')
        ? Object.defineProperty(Object.prototype, 'realType', { value: realType }) : Object.prototype['realType'] = realType;
})();

次に、次のように簡単に使用します:

obj.realType()  //  would return 'Object'
obj.realType(true)  //  would return 'object'

注:渡せる引数は1つです。がブール値の場合true、戻り値は常に小文字になります。

その他の例:

true.realType();                            //  "Boolean"
var a = 4; a.realType();                    //  "Number"
$('div:first').realType();                   // "jQuery"
document.createElement('div').realType()    //  "HTMLDivElement"

別のライブラリ(Moo、Proto、Yui、Dojoなど)を使用してオブジェクトが作成された時期を定義するなど、何か追加すべきことがあれば、遠慮なくコメントまたは編集してください。正確かつ正確。または、GitHub私が作成したものにロールオーバーして知らせてください。また、そこにcdn minファイルへのクイックリンクがあります。


2
function getType(obj) {
    if(obj && obj.constructor && obj.constructor.name) {
        return obj.constructor.name;
    }
    return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}

私の予備テストでは、これはかなりうまく機能しています。最初のケースは「新規」で作成されたオブジェクトの名前を出力し、2番目のケースは他のすべてをキャッチする必要があります。

(8, -1)結果は常に最初[objectと最後であると想定しているので使用してい]ますが、すべてのシナリオに当てはまるかどうかはわかりません。


2

私はここで最も普遍的な解決策を推測します- 最初に確認してundefinedからをnull呼び出すことconstructor.name.toLowerCase()です。

const getType = v =>
  v === undefined
    ? 'undefined'
    : v === null
      ? 'null'
      : v.constructor.name.toLowerCase();




console.log(getType(undefined)); // 'undefined'
console.log(getType(null)); // 'null'
console.log(getType('')); // 'string'
console.log(getType([])); // 'array'
console.log(getType({})); // 'object'
console.log(getType(new Set())); // `set'
console.log(getType(Promise.resolve())); // `promise'
console.log(getType(new Map())); // `map'

私の知る限り-には.constructor.name常に文字列値が含まれています。undefined / nullの場合、関数から返される適切な文字列があります。
Arsenowitch

ありがとう-私のコメントを削除します…
Bergi

以降constructorで作成されたオブジェクトの継承されたプロパティです、この休憩Object.create(null)。修正するのに十分簡単ですが、それを何と呼びますか?「[オブジェクトnull]」?
traktor53

0

typeof 条件は、変数タイプをチェックするために使用されます(if-else条件で変数タイプをチェックする場合)。

if(typeof Varaible_Name "undefined")
{

}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.