1. ホーム
  2. ジャバスクリプト

[解決済み】オブジェクトの型の名前を取得する

2022-03-23 05:57:45

質問

はあるのでしょうか? JavaScript に相当します。 ジャワ 's class.getName() ?

解決方法は?

<ブロッククオート

Java の class.getName() ?

いいえ .

ES2015 アップデート : の名前 class Foo {}Foo.name . の名前は thing のクラスに関係なく thing のタイプは thing.constructor.name . ES2015 環境の組み込みコンストラクタには、正しい name プロパティがあります。 (2).constructor.name"Number" .


しかし、ここでは様々なハックを紹介しますが、どれも一長一短で破綻しています。

このハックは、オブジェクトのプロトタイプを変更するもので、人々が嫌がるものです。

Object.prototype.getName = function() { 
   var funcNameRegex = /function (.{1,})\(/;
   var results = (funcNameRegex).exec((this).constructor.toString());
   return (results && results.length > 1) ? results[1] : "";
};

これで、すべてのオブジェクトが機能を持つようになります。 getName() これはコンストラクタの名前を文字列として返します。私は、これを FF3IE7 他の実装のことは言えません。

それが嫌なら、JavaScriptで型を決定する様々な方法についての議論を紹介します...。


最近、もう少し網羅的になるように更新したのですが、まだまだです。訂正は大歓迎です...

を使用することで constructor プロパティを使用します。

すべて object には、その constructor プロパティがありますが、その方法によっては object が構築され、その値で何をしたいかによって、役に立つか立たないかが決まります。

一般的には constructor プロパティを使って、このようにオブジェクトの型をテストすることができます。

var myArray = [1,2,3];
(myArray.constructor == Array); // true

ですから、ほとんどのニーズにはこれで十分です。とはいえ...

注意事項

動作しない すべて 多くの場合

このパターン、壊れているとはいえ、結構あるんですよね。

function Thingy() {
}
Thingy.prototype = {
    method1: function() {
    },
    method2: function() {
    }
};

Objects を介して構築された new Thingy を持つことになります。 constructor を指すプロパティです。 Object ではなく Thingy . というわけで、冒頭から失敗です。 constructor を、自分が管理していないコードベースで使うことができるのです。

多重継承

あまり知られていない例として、多重継承があります。

function a() { this.foo = 1;}
function b() { this.bar = 2; }
b.prototype = new a(); // b inherits from a

今、物事はあなたが期待するように動作しません。

var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true

そのため、もし object テストしている object として設定します。 prototype . これを回避する方法は、この議論の範囲外です。

には、他にも使い道があります。 constructor プロパティは、面白いものもあれば、そうでないものもあります。今のところ、この議論とは関係ないので、それらの用途について掘り下げることはしません。

クロスフレームやクロスウィンドウでは動作しない

使用方法 .constructor からのオブジェクトの型をチェックしたい場合、型チェックのために使用すると、壊れてしまいます。 window オブジェクト、例えば iframe やポップアップウィンドウのようなものです。これは、それぞれのコアタイプに異なるバージョンが存在するためです。 constructor をそれぞれの `window' で、すなわち

iframe.contentWindow.Array === Array // false


を使用しています。 instanceof 演算子...

instanceof 演算子は object 型と同様に、潜在的な問題があります。 constructor プロパティを使用します。

var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true

しかし instanceof はリテラル値に対して機能しません(なぜならリテラルは Objects )

3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false

リテラルは Object のために instanceof が機能するように、例えば

new Number(3) instanceof Number // true

.constructor のチェックは、リテラルに対してうまく機能します。 . メソッド呼び出しは、暗黙のうちにリテラルをそれぞれのオブジェクト型にラップしています。

3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true

なぜ3が2つのドットなのか?Javascriptが最初のドットを小数点以下として解釈するからです ;)

クロスフレーム、クロスウィンドウは動作しません。

instanceof と同じ理由で、異なるウィンドウをまたいで動作することはありません。 constructor プロパティのチェックを行います。


を使用することで name プロパティの constructor プロパティを...

動作しない すべて 多くの場合

これも上記を参照。 constructor は、まったくもって、間違っていて、役に立たない。

IE9では動作しません。

使用方法 myObjectInstance.constructor.name の名前を含む文字列が得られます。 constructor 関数が使用されますが、この関数に関する注意事項に従います。 constructor プロパティを使用します。

IE9以上の場合は モンキーパッチ対応 :

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s+([^\s(]+)\s*\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1] : "";
        },
        set: function(value) {}
    });
}

更新されたバージョン を当該記事より引用。これは記事が公開されてから3ヶ月後に追加されたもので、記事の著者であるMatthew Scharleyが使用を推奨しているバージョンです。この変更は、以下から着想を得ています。 潜在的な落とし穴を指摘するコメント を追加しました。

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s([^(]{1,})\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1].trim() : "";
        },
        set: function(value) {}
    });
}


Object.prototype.toStringの使用

ということが判明しました。 この記事の詳細 を使用することができます。 Object.prototype.toString - の低レベルで汎用的な実装である toString - すべての組み込み型に対して型を取得するために

Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]

次のような短いヘルパー関数を書くことができます。

function type(obj){
    return Object.prototype.toString.call(obj).slice(8, -1);
}

を削除し、型名のみを取得します。

type('abc') // String

しかし、それは Object は、すべてのユーザー定義型に対応します。


すべての人のための注意事項...

これらはすべて、1つの潜在的な問題を含んでいます。それは、問題のオブジェクトがどのように構築されたかという問題です。ここでは、さまざまなオブジェクトの構築方法と、さまざまな型チェックの方法が返す値について説明します。

// using a named function:
function Foo() { this.a = 1; }
var obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // true
(obj.constructor.name == "Foo");  // true

// let's add some prototypical inheritance
function Bar() { this.b = 2; }
Foo.prototype = new Bar();
obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // false
(obj.constructor.name == "Foo");  // false


// using an anonymous function:
obj = new (function() { this.a = 1; })();
(obj instanceof Object);              // true
(obj.constructor == obj.constructor); // true
(obj.constructor.name == "");         // true


// using an anonymous function assigned to a variable
var Foo = function() { this.a = 1; };
obj = new Foo();
(obj instanceof Object);      // true
(obj instanceof Foo);         // true
(obj.constructor == Foo);     // true
(obj.constructor.name == ""); // true


// using object literal syntax
obj = { foo : 1 };
(obj instanceof Object);            // true
(obj.constructor == Object);        // true
(obj.constructor.name == "Object"); // true

この例にはすべての組み合わせが含まれているわけではありませんが、あなたのニーズによって物事がどのように混乱するのかを知るには十分な数であることを願っています。もし、あなたが何を求めているかを正確に理解していなければ、微妙な点を理解することができないため、予想外のところでコードが壊れてしまうかもしれません。

注意事項

の議論 typeof 演算子は、一見すると見過ごされているように見えますが、実際には object は、非常に単純化されたものであるため、与えられた型である。というのは、非常に単純だからです。 typeof は重要ですが、今のところ、この議論にはあまり関係がないように感じています。しかし、私の心は、変化することにオープンです。)