JavaScriptオブジェクトを作成しましたが、そのオブジェクトのクラスをどのように判断することができますか?
Javaの.getClass()
メソッドに似たものが欲しいのですが。
JavaScriptにはJavaの getClass()
とまったく同じものはありません。これは主に、JavaScriptが プロトタイプベースの言語 であるのに対して、Javaが クラスベース のものであるのとは対照的です。
あなたがgetClass()
に何を必要としているかに応じて、JavaScriptにはいくつかのオプションがあります。
typeof
instanceof
obj.
constructor
func.
prototype
、proto
. isPrototypeOf
いくつかの例:
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
paramがあり、falseに設定すると gulp または grunt になります。
obj.constructor.name
現代のブラウザでは信頼できる方法です。 ES6ではFunction.name
が正式に標準に追加され、これがJavaScriptオブジェクトの「クラス」を文字列として取得する標準準拠の手段になりました。オブジェクトがvar obj = new MyClass()
でインスタンス化されている場合、 "MyClass"を返します。
数値の場合は "Number"、配列の場合は "Array"、関数の場合は "Function"などが返されます。通常は予想どおりに動作します。失敗する唯一のケースは、Object.create( null )
によってプロトタイプなしでオブジェクトが作成された場合、またはオブジェクトが匿名で定義された(名前のない)関数からインスタンス化された場合です。
コードを縮小している場合は、ハードコードされた文字列と比較するのは安全ではありません。たとえば、obj.constructor.name == "MyType"
を確認する代わりに、obj.constructor.name == MyType.name
を確認します。あるいは単にコンストラクター同士を比較するだけですが、各DOMにはコンストラクター関数の異なるインスタンスがあるため、DOMの境界を越えては機能しません。したがって、それらのコンストラクターでオブジェクト比較を行うことは機能しません。
奇妙なことに、constructor.name
はプロトタイプチェーンで使用される最も基本的な関数の名前を返します。残念ながら直感的にはわかりません。たとえば、B
がA
からプロトタイプ的に派生し、B
、b
の新しいインスタンスを作成した場合、b.constructor.name
は "A"を返しますが、これは間違っているようです。ただし、単一レベルのプロトタイプおよびすべてのプリミティブに対してはうまく機能します。
この関数は、Object.prototype.toString.call(someObject)
から"undefined"
、"null"
、または"class"
内の[object class]
のいずれかを返します。
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...
「疑似クラス」を取得するには、次のようにしてコンストラクタ関数を取得します。
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にはありません。
コンストラクタプロパティ を使用して、オブジェクトを作成したコンストラクタ関数への参照を取得できます。
function MyObject(){
}
var obj = new MyObject();
obj.constructor; // MyObject
実行時にオブジェクトの種類を確認する必要がある場合は、 instanceof 演算子を使用できます。
obj instanceof MyObject // true
下位互換性の切れ目のない記録であるECMAScript 6を維持するため、JavaScriptにはclass
タイプがありません(誰もがこれを理解しているわけではありません)。 doesプロトタイプを作成するためのclass
構文の一部としてclass
キーワードがありますが、まだクラスと呼ばれるものはありませんです。 JavaScriptは現在ではなく、従来のOOP言語ではなかったになっています。クラスの観点からJSを話すことは、誤解を招くか、プロトタイプの継承をまだ理解していないことを示すだけです(実際にそのままにしておきます)。
つまり、this.constructor
は、依然としてconstructor
関数への参照を取得する優れた方法です。 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年には、JavaScriptにclass
キーワードがありますが、クラスタイプはありません。 this.constructor
はコンストラクター関数を取得する最良の方法であり、this.constructor.prototype
はプロトタイプ自体へのアクセスを取得する最良の方法です。
私は今一般的に動作する状況があり、これを使用しました:
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"
object.constructor.toString()
がchomeで返されるのではなく、IEでfunction objectClass () {}
return [object objectClass]
が見つかりました。だから、私は http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects-のコードを考える 私はコードを修正した次のように:
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;
};
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... );
JavaScriptでは、クラスはありませんが、コンストラクタ名がほしいと思い、obj.constructor.toString()
が必要なものを教えてくれます。
Dfaに同意してください。名前付きクラスが見つからないときにプロトタイプをクラスと見なすのはそのためです。
これは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;
}
私のライブラリを試してみてください TypeScript-class-helpers :
import { CLASS } from 'TypeScript-class-helpers'
@CLASS.NAME('Example')
class Example {
}
console.log(CLASS.getName(Example) === 'Example') // true
console.log(CLASS.getNameFromObject(new Example()) === 'Example') // true
console.log(CLASS.getBy('Example') === Example) // true
こうすると、uglifyプロセスの後でもクラス名を使うことができます。
インストール:
npm i TypeScript-class-helpers
Javascriptはクラスのない言語です。Javaのようにクラスの振る舞いを静的に定義するクラスはありません。 JavaScriptは、メソッドや継承など、オブジェクトのプロパティを定義するためにクラスではなくプロトタイプを使用します。 JavaScriptのプロトタイプを使用して、多くのクラスベースの機能をシミュレートすることが可能です。