JavaScriptオブジェクトのクラスを取得する方法は?


728

JavaScriptオブジェクトを作成しましたが、そのオブジェクトのクラスをどのように判別できますか?

Javaの.getClass()方法に似たものが欲しいのですが。


6
たとえば、次のようなPersonを作成します。var p = new Person(); 「p」という名前のPersonオブジェクトがありますが、「p」を使用してクラス名「Person」を取得するにはどうすればよいですか。
DNB5brims 2009


更新:ECMAScript 6の時点で、JavaScriptにはまだclassタイプがありません。それはありません持っているclassキーワードとclass方法がより簡単にアクセスすることが可能なプロトタイプを作成するための構文をsuper
james_womack 2016

Object.classNameはどうですか?
Paul Basenko 2017年

@ Paul-Basenko: "className"はオブジェクトのクラスを通知しませんが、CSSクラスを参照するHTML要素の "class"プロパティのコンテンツを返します。また、「classList」を使用してそれらを簡単に管理することもできますが、OPの質問とは関係ありません。
黒曜石

回答:


1009

getClass()JavaScriptでのJavaに正確に対応するものはありません。ほとんどは、JavaScriptがプロトタイプベースの言語であるためです。Javaがクラスではなく、であるです。

必要なものに応じてgetClass()、JavaScriptにはいくつかのオプションがあります。

いくつかの例:

function Foo() {}
var foo = new Foo();

typeof Foo;             // == "function"
typeof foo;             // == "object"

foo instanceof Foo;     // == true
foo.constructor.name;   // == "Foo"
Foo.name                // == "Foo"    

Foo.prototype.isPrototypeOf(foo);   // == true

Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21);            // == 42

注:Uglifyを使用してコードをコンパイルしている場合は、グローバルでないクラス名が変更されます。これを防ぐために、Uglifyを持っている--mangleあなたが使用しているfalseに設定することができていることのparam ゴクゴクうなり声を


6
それはおそらくありますfunc.prototype(はい、関数はオブジェクトですが、prototypeプロパティは関数オブジェクトにのみ関連します)。
マイル

5
あなたはまた、instanceof/ isPrototypeOf()そして非標準に言及したいかもしれません__proto__
クリストフ

9
ES5はaditionallyありObject.getPrototypeOf()
クリストフ・

22
警告constructor.nameコードが縮小化されているかどうかに依存しないでください。関数名は任意に変更されます。
igorsantos07 2016年

3
@ igorsantos07、少なくとも2019年。「オンラインJavaScriptミニファイア」の上位5〜10件のGoogle検索結果は、construction.name無視される/最小化されないトークンとして認識されます。(すべてではないにしても)ほとんどの縮小ソフトウェアは例外ルールを提供します。
バルカンレイヴン

296
obj.constructor.name

最新のブラウザでは信頼できる方法です。Function.nameES6の標準に正式に追加され、JavaScriptオブジェクトの「クラス」を文字列として取得する標準準拠の手段になりました。オブジェクトが次のようにインスタンス化されている場合var obj = new MyClass()「MyClass」を返します。

数値の場合は「Number」、配列の場合は「Array」、関数の場合は「Function」などが返されます。通常、期待どおりに動作します。失敗するのは、オブジェクトがを介してプロトタイプなしで作成された場合Object.create( null )、またはオブジェクトが匿名で定義された(名前のない)関数からインスタンス化された場合のみです。

また、コードを縮小する場合、ハードコードされた型文字列と比較するのは安全ではないことにも注意してください。たとえばobj.constructor.name == "MyType"、ifをチェックする代わりに、代わりにチェックしobj.constructor.name == MyType.nameます。または、コンストラクタ自体を比較するだけですが、各DOMにはコンストラクタ関数の異なるインスタンスがあるため、これはDOMの境界を越えて機能しません。したがって、それらのコンストラクタでオブジェクト比較を実行しても機能しません。


11
Function.name(まだ)JavaScript標準の一部ではありません。現在ChromeとFirefoxでサポートされていますが、IE(10)ではサポートされていません。
Halcyon 2013年

13
obj.constructor.name名前付き関数でのみ機能します。つまり、を定義するvar Foo = function() {}と、for var foo = new Foo()foo.constructor.name空の文字列を返します。
KFL、2014

29
警告constructor.nameコードが縮小化されているかどうかに依存しないでください。関数名は任意に変更されます。
igorsantos07 2016年

1
Function.nameはES6の一部です。developer.mozilla.org/ en
Janus Troelsen

1
@adalbertpl ES6以前は、プロトタイプを手動でチェーンする必要がありました。constructor.nameES6の新しいクラスサポートで期待どおりに動作することを知っておくと便利です。
devios1

29

この関数は"Undefined"、未定義の値と"Null"null に対して戻ります。
他のすべての値の場合、CLASSNAME-partはから抽出されます[object CLASSNAME]。これはを使用した結果ですObject.prototype.toString.call(value)

function getClass(obj) {
  if (typeof obj === "undefined") return "Undefined";
  if (obj === null) return "Null";
  return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}

getClass("")   === "String";
getClass(true) === "Boolean";
getClass(0)    === "Number";
getClass([])   === "Array";
getClass({})   === "Object";
getClass(null) === "Null";
// etc...

Object.prototype.getClass = function(){objの代わりに 'this'を使用するとよい
SparK

2
もちろん、nullとundefinedはチェックできません。これは、ObjectだけがgetClassメソッドを持つためです
SparK

8
これはネイティブオブジェクトでのみ機能します。継承の種類がある場合は、常に取得し"Object"ます。
Halcyon 2013年

ええ、関数の最後の行はちょうどでなければなりませんreturn obj.constructor.name。同じ結果が得られ、さらに非ネイティブオブジェクトも処理されます。
スティーブベネット

18

「疑似クラス」を取得するには、次のようにしてコンストラクター関数を取得できます。

obj.constructor

constructor継承を行うときにが正しく設定されていると仮定します-これは次のようなものです

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

そして、これらの2行と一緒に:

var woofie = new Dog()

woofie.constructorポイントになりDogます。注Dogコンストラクタ関数で、あるFunctionオブジェクト。しかし、あなたはできるif (woofie.constructor === Dog) { ... }

クラス名を文字列として取得したい場合は、次のコードがうまく機能していることがわかりました。

http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects

function getObjectClass(obj) {
    if (obj && obj.constructor && obj.constructor.toString) {
        var arr = obj.constructor.toString().match(
            /function\s*(\w+)/);

        if (arr && arr.length == 2) {
            return arr[1];
        }
    }

    return undefined;
}

コンストラクター関数を取得して文字列に変換し、コンストラクター関数の名前を抽出します。

obj.constructor.nameうまくいくかもしれないが、それは標準ではないことに注意してください。これはChromeとFirefoxにありますが、IE 9またはIE 10 RTMを含むIEにはありません。


13

オブジェクトを作成したコンストラクター関数への参照は、constructorプロパティを使用して取得できます

function MyObject(){
}

var obj = new MyObject();
obj.constructor; // MyObject

実行時にオブジェクトのタイプを確認する必要がある場合は、instanceof演算子を使用できます。

obj instanceof MyObject // true

それはコンストラクタ関数自体を返しませんか?たとえば、もう一度呼び出して、その型の新しいオブジェクトを作成できますか?
SparK 2012年

1
@SparKはい。ただし、同じDOMを使用している限り(関数オブジェクトを比較している限り)、これを比較に使用できます。ただし、特にiframeを使用するとDOMの境界を越えて機能するため、コンストラクターを文字列に変換して比較することをお勧めします。
devios1

この回答は「クラス」(または少なくとも、クラスのインスタンスを作成するために使用できるオブジェクトのハンドル-「クラス」と同じです)を返します。上記は、「クラスオブジェクト」と同じではない、返されたすべての文字列に答えます(以前のように)。
Mike P.

8

後方互換性の絶え間ない記録であるECMAScript 6を維持するために、JavaScriptにはまだclass型がありません(すべての人がこれを理解しているわけではありません)。それはありません持っているclassそのの一部としてキーワードをclassプロトタイプ-が、作成するための構文クラスと呼ばれる、まだありません事を。JavaScriptは現在ではなく、かつて古典的なOOP言語ではありませんでした。クラスの観点からJSを話すことは、誤解を招くか、またはプロトタイプの継承をまだグロッキン化していないことを示しているだけです(それを現実に保つだけです)。

つまりthis.constructorconstructor関数への参照を取得するための優れた方法です。そして、this.constructor.prototype試作品自体にアクセスする方法です。これはJavaではないので、クラスではありません。これは、インスタンスがインスタンス化されたプロトタイプオブジェクトです。ES6構文糖を使用してプロトタイプチェーンを作成する例を次に示します。

class Foo {
  get foo () {
    console.info(this.constructor, this.constructor.name)
    return 'foo'
  }
}

class Bar extends Foo {
  get foo () {
    console.info('[THIS]', this.constructor, this.constructor.name, Object.getOwnPropertyNames(this.constructor.prototype))
    console.info('[SUPER]', super.constructor, super.constructor.name, Object.getOwnPropertyNames(super.constructor.prototype))

    return `${super.foo} + bar`
  }
}

const bar = new Bar()
console.dir(bar.foo)

これはそれを使用して出力するものですbabel-node

> $ babel-node ./foo.js                                                                                                                    6.2.0 master ●]
[THIS] [Function: Bar] 'Bar' [ 'constructor', 'foo' ]
[SUPER] [Function: Foo] 'Foo' [ 'constructor', 'foo' ]
[Function: Bar] 'Bar'
'foo + bar'

そこにあります!2016年、classJavaScriptにはキーワードがありますが、それでもクラスタイプはありません。this.constructorコンストラクタ関数this.constructor.prototypeを取得する最良の方法であり、プロトタイプ自体にアクセスする最良の方法です。


7

私は今ジェネリックで動作する状況があり、これを使用しました:

class Test {
  // your class definition
}

nameByType = function(type){
  return type.prototype["constructor"]["name"];
};

console.log(nameByType(Test));

これが、オブジェクトのインスタンスがない場合にタイプ入力によってクラス名を取得する唯一の方法です。

(ES2017で作成)

ドット表記もうまくいきます

console.log(Test.prototype.constructor.name); // returns "Test" 

ああ、これは私が探していたものです。インスタンス化されていない場合は、「プロトタイプ」を使用してクラス名を取得する必要があります。トンありがとう!
Artokun 2018

4

ES6のJavaScriptクラスでは、を使用できますobject.constructor。以下のサンプルクラスでは、getClass()メソッドは期待どおりにES6クラスを返します。

var Cat = class {

    meow() {

        console.log("meow!");

    }

    getClass() {

        return this.constructor;

    }

}

var fluffy = new Cat();

...

var AlsoCat = fluffy.getClass();
var ruffles = new AlsoCat();

ruffles.meow();    // "meow!"

getClassメソッドからクラスをインスタンス化する場合は、必ずブラケットで囲むようにしてください。ruffles = new ( fluffy.getClass() )( args... );


3

私は丁目で返されるのではなく、IEでobject.constructor.toString()返却を見つけます。だから、私はhttp://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objectsのコードがIEでうまく機能しない可能性があると思います。次のようにコードを修正しました。[object objectClass]function objectClass () {}

コード:

var getObjectClass = function (obj) {
        if (obj && obj.constructor && obj.constructor.toString()) {

                /*
                 *  for browsers which have name property in the constructor
                 *  of the object,such as chrome 
                 */
                if(obj.constructor.name) {
                    return obj.constructor.name;
                }
                var str = obj.constructor.toString();
                /*
                 * executed if the return of object.constructor.toString() is 
                 * "[object objectClass]"
                 */

                if(str.charAt(0) == '[')
                {
                        var arr = str.match(/\[\w+\s*(\w+)\]/);
                } else {
                        /*
                         * executed if the return of object.constructor.toString() is 
                         * "function objectClass () {}"
                         * for IE Firefox
                         */
                        var arr = str.match(/function\s*(\w+)/);
                }
                if (arr && arr.length == 2) {
                            return arr[1];
                        }
          }
          return undefined; 
    };

2

JavaScriptにはクラスはありませんが、コンストラクター名obj.constructor.toString()が必要で、必要なものを教えてくれると思います。


1
これにより、コンストラクター関数の定義全体が文字列として返されます。あなたが本当に欲しいのは.nameです。
devios1 2012年

4
しかし.nameでもIE 9で定義されていません
nonopolarity

1

dfaに同意します。そのため、名前付きクラスが見つからない場合は、prototyeをクラスと見なします。

Eli Greyが投稿した機能を、私の考え方に合わせてアップグレードしたものです。

function what(obj){
    if(typeof(obj)==="undefined")return "undefined";
    if(obj===null)return "Null";
    var res = Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
    if(res==="Object"){
        res = obj.constructor.name;
        if(typeof(res)!='string' || res.length==0){
            if(obj instanceof jQuery)return "jQuery";// jQuery build stranges Objects
            if(obj instanceof Array)return "Array";// Array prototype is very sneaky
            return "Object";
        }
    }
    return res;
}

1

クラスを取得するだけでなく、インスタンスだけから拡張する必要がある場合は、次のように記述します。

持ってみましょう

 class A{ 
   constructor(name){ 
     this.name = name
   }
 };

 const a1 = new A('hello a1');

したがって、インスタンスのみを使用してAを拡張するには、

const a2 = new ((Object.getPrototypeOf(a)).constructor())('hello a2')
// the analog of const a2 = new A()

console.log(a2.name)//'hello a2'

0

私は使用することをお勧めしObject.prototype.constructor.nameます:

Object.defineProperty(Object.prototype, "getClass", {
    value: function() {
      return this.constructor.name;
    }
});

var x = new DOMParser();
console.log(x.getClass()); // `DOMParser'

var y = new Error("");
console.log(y.getClass()); // `Error'

0

ここでの実装だgetClass()getInstance()

を使用して、オブジェクトのクラスの参照を取得できthis.constructorます。

インスタンスコンテキストから:

function A() {
  this.getClass = function() {
    return this.constructor;
  }

  this.getNewInstance = function() {
    return new this.constructor;
  }
}

var a = new A();
console.log(a.getClass());  //  function A { // etc... }

// you can even:
var b = new (a.getClass());
console.log(b instanceof A); // true
var c = a.getNewInstance();
console.log(c instanceof A); // true

静的コンテキストから:

function A() {};

A.getClass = function() {
  return this;
}

A.getInstance() {
  return new this;
}

2
なぜthis.constructorですか?
ソロモンウッコ

1
よくわかりませんが、それがより良い場合は、間違いなくコミュニティを対象にして、答えを編集して改善することができます。
Bruno Finger

0

このようなこともできます

 class Hello {
     constructor(){
     }
    }
    
      function isClass (func) {
        return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func))
    }
    
   console.log(isClass(Hello))

これは、入力がクラスかどうかを教えてくれます


-2

JavaScriptはクラスのない言語です。Javaのようにクラスの動作を静的に定義するクラスはありません。JavaScriptは、メソッドや継承などのオブジェクトプロパティを定義するために、クラスではなくプロトタイプを使用します。JavaScriptのプロトタイプを使用して、多くのクラスベースの機能をシミュレートすることが可能です。


12
私はよくJavascriptにクラスがないと言ってきました:)
スティーブン

4
更新:ECMAScript 6の時点で、JavaScriptにはまだclassタイプがありません。それはありません持っているclassキーワードとclass方法がより簡単にアクセスすることが可能なプロトタイプを作成するための構文をsuper
james_womack

-3

質問はすでに回答されているようですが、Javaの場合と同様に、OPはオブジェクトのクラスにアクセスする必要があり、選択した回答では不十分です(私見)。

次の説明で、オブジェクトのクラスを取得できます(実際にはJavaScriptではプロトタイプと呼ばれます)。

var arr = new Array('red', 'green', 'blue');
var arr2 = new Array('white', 'black', 'orange');

次のようなプロパティを追加できます。

Object.defineProperty(arr,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue

ただし、.lastプロパティはarr、配列プロトタイプからインスタンス化された ' 'オブジェクトでのみ使用できます。したがって、.lastプロパティをArrayプロトタイプからインスタンス化されたすべてのオブジェクトで使用できるようにするには.last、Arrayプロトタイプのプロパティを定義する必要があります。

Object.defineProperty(Array.prototype,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

ここでの問題は、 ' arr'および ' arr2'変数がどのオブジェクトタイプ(プロトタイプ)に属するかを知っている必要があることです。つまり、 ' arr'オブジェクトのクラスタイプ(プロトタイプ)がわからない場合、それらのプロパティを定義することはできません。上記の例では、arrがArrayオブジェクトのインスタンスであることを認識しているため、Array.prototypeを使用してArrayのプロパティを定義しました。しかし、 ' arr'のクラス(プロトタイプ)を知らなかった場合はどうなりますか?

Object.defineProperty(arr.__proto__,'last2', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

ご覧のとおり、「arr」が配列であることを知らなくても、「arr」を使用して「arr.__proto__」のクラスを参照するだけの新しいプロパティを追加できます。

' arr'のプロトタイプにアクセスしたのは、それがArrayのインスタンスであることを知らずに、OPが要求したことだと思います。


この__proto__プロパティは廃止されており、prototypeプロパティに対する利点はほとんどありません。
Sapphire_Brick
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.