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.
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:
typeof
instanceof
obj.
_ constructor
func.
_ prototype
, proto
. isPrototypeOf
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 .
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.
É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.
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...
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.
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
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.
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"
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:
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;
};
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... );
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.
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;
}
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
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.