web-dev-qa-db-fra.com

Comment obtenir la classe d'un objet JavaScript?

J'ai créé un objet JavaScript, mais comment puis-je déterminer la classe de cet objet?

Je veux quelque chose de similaire à la méthode .getClass() de Java.

622
DNB5brims

Il n'y a pas d'équivalent exact à Java getClass() en JavaScript. Cela est principalement dû au fait que JavaScript est un langage prototype , alors que Java est un basé sur la classe un.

En fonction de vos besoins, getClass(), JavaScript comporte plusieurs options:

Quelques exemples:

_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
_

Remarque: si vous compilez votre code avec Uglify, les noms de classe non globaux seront modifiés. Pour éviter cela, Uglify a un paramètre --mangle que vous pouvez définir sur false et utilisant gulp ou grognement .

879
earl
obj.constructor.name

est une méthode fiable dans les navigateurs modernes. Function.name a été officiellement ajouté à la norme dans ES6, ce qui en fait un moyen conforme à la norme d'obtenir la "classe" d'un objet JavaScript sous forme de chaîne. Si l'objet est instancié avec var obj = new MyClass(), il retournera "MyClass".

Il retournera "Number" pour les nombres, "Array" pour les tableaux et "Function" pour les fonctions, etc. Il se comporte généralement comme prévu. Les seuls cas d'échec sont les suivants: si un objet est créé sans prototype, via Object.create( null ), ou si l'objet a été instancié à partir d'une fonction définie anonymement (sans nom).

Notez également que si vous réduisez votre code, la comparaison avec des chaînes de caractères codées en dur n'est pas sûre. Par exemple, au lieu de vérifier si obj.constructor.name == "MyType", vérifiez plutôt obj.constructor.name == MyType.name. Ou simplement comparer les constructeurs eux-mêmes, mais cela ne fonctionnera pas au-delà des limites du DOM, car il existe différentes instances de la fonction constructeur sur chaque DOM. Par conséquent, une comparaison d'objet sur leurs constructeurs ne fonctionnera pas.

Remarque lors de l'enchaînement de prototypes

Édition: Ceci est apparemment discutable maintenant que ES6 supporte mieux les classes et l'héritage. Comme l'explique adalbertpl, constructor.name se comporte comme prévu dans ce scénario.

Curieusement, constructor.name renvoie le nom de la fonction la plus à la base utilisée dans une chaîne de prototypes, ce qui n’est malheureusement pas intuitif. Par exemple, si B dérive de manière prototypique de A et que vous créez une nouvelle instance de B, b, b.constructor.name renvoie "A", ce qui semble erroné. Cela fonctionne bien pour les prototypes à un seul niveau et toutes les primitives, cependant.

257
devios1

Cette fonction renvoie soit "undefined", "null", soit le "class" dans [object class] de Object.prototype.toString.call(someObject).

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...
27
Eli Grey

Pour obtenir la "pseudo classe", vous pouvez obtenir la fonction constructeur, par

obj.constructor

en supposant que la variable constructor est correctement définie lorsque vous effectuez l'héritage, ce qui correspond à quelque chose comme:

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

et ces deux lignes, avec:

var woofie = new Dog()

fera que woofie.constructor pointe sur Dog. Notez que Dog est une fonction constructeur et un objet Function. Mais vous pouvez faire if (woofie.constructor === Dog) { ... }.

Si vous voulez obtenir le nom de la classe sous forme de chaîne, j'ai trouvé que ça marche bien:

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;
}

Il accède à la fonction constructeur, la convertit en chaîne et extrait le nom de la fonction constructeur.

Notez que obj.constructor.name aurait pu bien fonctionner, mais ce n'est pas standard. Il se trouve sur Chrome et Firefox, mais pas sur Internet Explorer, y compris IE 9 ou IE 10 RTM.

17

Vous pouvez obtenir une référence à la fonction constructeur qui a créé l'objet en utilisant propriété du constructeur :

function MyObject(){
}

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

Si vous devez confirmer le type d'un objet au moment de l'exécution, vous pouvez utiliser l'opérateur instanceof :

obj instanceof MyObject // true
11
CMS

Conformément à son record ininterrompu de compatibilité ascendante, ECMAScript 6, JavaScript n’a toujours pas de type class (même si tout le monde ne le comprend pas). Il possède un mot clé class dans le cadre de sa syntaxe class pour la création de prototypes, mais toujours pas de chose appelée class . JavaScript n'est pas maintenant et n'a jamais été un langage classique OOP . Parler de JS en termes de classe est seulement soit trompeur, soit un signe d'héritage prototypique qui n'a pas encore valu la peine d'être pris (tout simplement le garder réel).

Cela signifie que this.constructor est toujours un excellent moyen d’obtenir une référence à la fonction constructor. Et this.constructor.prototype est le moyen d'accéder au prototype lui-même. Comme ce n'est pas Java, ce n'est pas une classe. C'est l'objet prototype à partir duquel votre instance a été instanciée. Voici un exemple utilisant le sucre syntaxique ES6 pour créer une chaîne de prototypes:

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)

C'est ce qui sort en utilisant 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'

Voilà! En 2016, il existe un mot clé class en JavaScript, mais toujours pas de type de classe. this.constructor est le meilleur moyen d'obtenir la fonction constructeur, this.constructor.prototype le meilleur moyen d'accéder au prototype lui-même.

5
james_womack

j'ai eu une situation de travailler générique maintenant et utilisé ceci:

class Test {
  // your class definition
}

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

console.log(nameByType(Test));

c’est le seul moyen que j’ai trouvé pour obtenir le nom de la classe par type si vous n’avez pas d’instance d’objet.

(écrit en ES2017)

la notation par points fonctionne aussi très bien

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

Je trouve object.constructor.toString() return [object objectClass] dans IE, plutôt que function objectClass () {} est retourné dans chome. Donc, je pense que le code http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects peut ne pas fonctionner correctement dans IE.And I corrigé le code comme suit:

code:

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; 
    };
3
zzy7186

Pour les classes Javascript dans ES6, vous pouvez utiliser object.constructor. Dans l'exemple de classe ci-dessous, la méthode getClass() renvoie la classe ES6 comme prévu:

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!"

Si vous instanciez la classe à partir de la méthode getClass, assurez-vous de la mettre entre crochets, par exemple. ruffles = new ( fluffy.getClass() )( args... );

3
Hugheth

En javascript, il n'y a pas de classes, mais je pense que vous voulez le nom du constructeur et obj.constructor.toString() vous dira ce dont vous avez besoin.

2
Jikhan

Je suis d’accord avec dfa, c’est pourquoi je considère le prototype comme la classe quand aucune classe nommée n’a été trouvée

Voici une fonction améliorée de celle publiée par Eli Gray, pour correspondre à ma façon de penser

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
Antkhan

Essayez ma bibliothèque 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

De cette façon, vous pouvez utiliser vos noms de classe même après le processus d'ugification.

Installation:

npm i TypeScript-class-helpers
0
Dariusz Filipiak

Javascript est un langage sans classe: aucune classe ne définit le comportement d'une classe de manière statique comme en Java. JavaScript utilise des prototypes au lieu de classes pour définir les propriétés des objets, y compris les méthodes et l'héritage. Il est possible de simuler de nombreuses fonctionnalités basées sur les classes avec des prototypes en JavaScript.

0
dfa