Como obter a classe de um objeto JavaScript?


728

Eu criei um objeto JavaScript, mas como posso determinar a classe desse objeto?

Eu quero algo semelhante ao .getClass()método Java .


6
por exemplo, eu faço uma Pessoa assim: var p = new Person (); Eu tenho um Objeto Pessoa chamado "p", como posso usar "p" para recuperar o nome da Classe: "Pessoa".
DNB5brims 08/08/09


Atualização: A partir do ECMAScript 6, o JavaScript ainda não possui um classtipo. Ele faz ter uma classpalavra-chave e classsintaxe para a criação de protótipos em que os métodos podem mais facilmente acesso super.
James_womack

E o Object.className?
Paul Basenko

@ Paul-Basenko: "className" não informa a classe do objeto, mas retorna o conteúdo da propriedade "class" de um elemento HTML, que se refere às classes CSS. Você também deseja usar o "classList" para gerenciá-los facilmente, mas não está relacionado à pergunta do OP.
Obsidian

Respostas:


1009

Não há contrapartida exata do Java getClass()em JavaScript. Principalmente porque o JavaScript é uma linguagem baseada em protótipo , em vez de Java ser uma linguagem baseada em classe .

Dependendo do que você precisa getClass(), existem várias opções em JavaScript:

Alguns exemplos:

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

Nota: se você estiver compilando seu código com o Uglify, ele mudará os nomes de classes não globais. Para evitar isso, o Uglify tem um --mangleparâmetro que você pode definir como false usando gulp ou grunt .


6
Provavelmente deveria ser func.prototype(sim, funções são objetos, mas a prototypepropriedade é relevante apenas em objetos de função).
Miles

5
você também pode querer mencionar instanceof/ isPrototypeOf()ea não-padrão__proto__
Christoph

9
ES5 adicionalmenteObject.getPrototypeOf()
Christoph

22
Aviso : não confie constructor.namese seu código estiver sendo minificado. O nome da função mudará arbitrariamente.
igorsantos07

3
@ igorsantos07, pelo menos em 2019; os 5-10 principais resultados do google para "on-line javascript minifier" reconhecem construction.namecomo um token a ser ignorado / não minimizado. Além da maioria dos softwares minificadores (se não todos), eles fornecem regras de exceção.
corvo vulcan

297
obj.constructor.name

é um método confiável em navegadores modernos. Function.namefoi oficialmente adicionado ao padrão no ES6, tornando-o um meio compatível com os padrões de obter a "classe" de um objeto JavaScript como uma string. Se o objeto for instanciado var obj = new MyClass(), ele retornará "MyClass".

Ele retornará "Número" para números, "Matriz" para matrizes e "Função" para funções, etc. Geralmente se comporta conforme o esperado. Os únicos casos em que falha é se um objeto é criado sem um protótipo, via Object.create( null )ou se o objeto foi instanciado a partir de uma função definida anonimamente (sem nome).

Observe também que, se você estiver minificando seu código, não é seguro comparar com cadeias de caracteres codificadas. Por exemplo, em vez de verificar se obj.constructor.name == "MyType", verifique obj.constructor.name == MyType.name. Ou apenas compare os próprios construtores, no entanto, isso não funcionará através dos limites do DOM, pois existem instâncias diferentes da função do construtor em cada DOM, portanto, fazer uma comparação de objetos nos construtores não funcionará.


11
Function.nameainda não faz parte do padrão JavaScript. Atualmente, ele é suportado no Chrome e Firefox, mas não no IE (10).
quer

13
obj.constructor.namefunciona apenas para funções nomeadas . Ou seja, se eu definir var Foo = function() {}, então for var foo = new Foo(), foo.constructor.namefornecerá uma string vazia.
KFL

29
Aviso : não confie constructor.namese seu código estiver sendo minificado. O nome da função mudará arbitrariamente.
igorsantos07


1
@adalbertpl Tinha a ver com encadear protótipos manualmente, antes do ES6. É bom saber constructor.namese comportar conforme o esperado com o novo suporte de classe no ES6.
Devios1

29

Esta função retorna "Undefined"para valores indefinidos e "Null"para nulos.
Para todos os outros valores, a CLASSNAMEparte-é extraída [object CLASSNAME], que é o resultado do uso 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 () {using 'this' em vez de obj seria bom
faísca

2
é claro, em seguida, nulos e indefinidos seria inatingível uma vez que apenas o objeto teria a getClass método
faísca

8
Isso funciona apenas em objetos nativos. Se você tem algum tipo de herança, sempre receberá "Object".
quer

Sim, a última linha da função deve ser apenas return obj.constructor.name. Isso fornece os mesmos resultados e também lida com objetos não nativos.
Steve Bennett

18

Para obter a "pseudo classe", você pode obter a função construtora,

obj.constructor

assumindo que o constructorestá definido corretamente quando você faz a herança - que é algo como:

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

e essas duas linhas, juntamente com:

var woofie = new Dog()

fará woofie.constructorquestão de Dog. Observe que Dogé uma função construtora e é um Functionobjeto. Mas você pode fazer if (woofie.constructor === Dog) { ... }.

Se você deseja obter o nome da classe como uma string, achei o seguinte funcionando bem:

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

Ele chega à função construtora, converte-a em string e extrai o nome da função construtora.

Observe que obj.constructor.namepoderia ter funcionado bem, mas não é padrão. Está no Chrome e Firefox, mas não no IE, incluindo o IE 9 ou IE 10 RTM.


13

Você pode obter uma referência à função construtora que criou o objeto usando a propriedade construtor :

function MyObject(){
}

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

Se você precisar confirmar o tipo de um objeto em tempo de execução, poderá usar a instância do operador:

obj instanceof MyObject // true

não retorna a própria função construtora, como, você pode chamá-la novamente e criar um novo objeto desse tipo?
SparK

1
@SparK Sim, embora você ainda possa usá-lo para uma comparação, desde que esteja no mesmo DOM (você está comparando objetos de função). No entanto, é uma prática muito melhor transformar o construtor em uma sequência e compará-la, especificamente porque funciona através dos limites do DOM ao usar iframes.
Devios1

Esta resposta retorna a "classe" (ou pelo menos manipula o objeto que pode ser usado para criar uma instância da classe - que é a mesma que "a classe"). O acima responde a todas as strings retornadas que não são iguais ao "objeto de classe" (por assim dizer).
Mike P.

8

De acordo com seu registro ininterrupto de compatibilidade com versões anteriores, o ECMAScript 6, o JavaScript ainda não possui um classtipo (embora nem todos entendam isso). Ele faz ter uma classpalavra-chave como parte de sua classsintaxe para a criação de protótipos, mas ainda não há coisa chamada classe . O JavaScript não é agora e nunca foi uma linguagem clássica de POO . Falar de JS em termos de classe é apenas enganoso ou um sinal de herança prototípica ainda não gritante (apenas mantendo-a real).

Isso significa que this.constructorainda é uma ótima maneira de obter uma referência para a constructorfunção. E this.constructor.prototypeé o caminho para acessar o próprio protótipo. Como este não é Java, não é uma classe. É o objeto de protótipo do qual sua instância foi instanciada. Aqui está um exemplo usando o açúcar sintático ES6 para criar uma cadeia de protótipos:

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)

Isto é o que isso gera usando 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'

Aí está! Em 2016, há uma classpalavra - chave em JavaScript, mas ainda não existe um tipo de classe. this.constructoré a melhor maneira de obter a função construtora, this.constructor.prototypea melhor maneira de obter acesso ao próprio protótipo.


7

Eu tive uma situação para trabalhar genérico agora e usei isso:

class Test {
  // your class definition
}

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

console.log(nameByType(Test));

essa é a única maneira que encontrei para obter o nome da classe por tipo input, se você não tiver uma instância de um objeto.

(escrito em ES2017)

notação de ponto também funciona bem

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

Ah, era isso que eu estava procurando. Se não for instanciado, você precisará usar 'prototype' para obter o nome da classe. Muito obrigado!
Artokun

4

Para Classes Javascript no ES6, você pode usar object.constructor. Na classe de exemplo abaixo, o getClass()método retorna a classe ES6 conforme o esperado:

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

Se você instanciar a classe a partir do getClassmétodo, envolva-a entre colchetes, por exemploruffles = new ( fluffy.getClass() )( args... );


3

Encontro object.constructor.toString()retorno [object objectClass]no IE, em vez de function objectClass () {}retornar no chome. Portanto, acho que o código em http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects pode não funcionar bem no IE.E eu corrigi o código da seguinte maneira:

código:

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

Em javascript, não há classes, mas acho que você deseja o nome do construtor e obj.constructor.toString()dirá o que você precisa.


1
Isso retornará toda a definição da função construtora como uma sequência. O que você realmente quer é .name.
Devios1

4
mas .namenão está definido ainda no IE 9
nonopolarity

1

Concordo com o dfa, é por isso que considero o protótipo como a classe quando nenhuma classe nomeada foi encontrada

Aqui está uma função atualizada da postada por Eli Gray, para combinar com meu modo de pensar

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

Se você precisar não apenas da classe GET, mas também EXTENDER que ela tenha apenas uma instância, escreva:

vamos ter

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

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

para estender A tendo a instância apenas use:

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

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

0

Sugiro usar 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

Aqui está uma implementação getClass()egetInstance()

Você pode obter uma referência para a classe de um objeto usando this.constructor.

Em um contexto de instância:

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

Do contexto estático:

function A() {};

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

A.getInstance() {
  return new this;
}

2
Por que não apenas this.constructor?
Solomon Ucko

1
Não sei, mas se for melhor, você pode definitivamente editar a resposta para melhorá-la à medida que achar melhor, depois de tudo isso é uma comunidade.
de Bruno Dedo

0

Você também pode fazer algo assim

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

Isso informará se a entrada é classe ou não


-2

Javascript é uma linguagem sem classe: não há classes que definam o comportamento de uma classe estaticamente como em Java. O JavaScript usa protótipos em vez de classes para definir propriedades do objeto, incluindo métodos e herança. É possível simular muitos recursos baseados em classe com protótipos em JavaScript.


12
Eu já disse muitas vezes que o Javascript carece de classe :)
Steven

4
Atualização: A partir do ECMAScript 6, o JavaScript ainda não possui um classtipo. Ele faz ter uma classpalavra-chave e classsintaxe para a criação de protótipos em que os métodos podem mais facilmente acesso super.
James_womack 01/08/19

-3

A pergunta parece já respondida, mas o OP deseja acessar a classe e o objeto, assim como fazemos em Java e a resposta selecionada não é suficiente (imho).

Com a seguinte explicação, podemos obter uma classe de um objeto (na verdade, é chamado de protótipo em javascript).

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

Você pode adicionar uma propriedade como esta:

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

Mas a .lastpropriedade estará disponível apenas para arro objeto que é instanciado a partir do protótipo Array. Portanto, para que a .lastpropriedade esteja disponível para todos os objetos instanciados no protótipo Array, precisamos definir a .lastpropriedade para o protótipo Array:

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

O problema aqui é que você precisa saber a que tipo de objeto (protótipo) as variáveis ' arr' e ' arr2' pertencem! Em outras palavras, se você não souber o tipo de classe (protótipo) do arrobjeto ' ', não poderá definir uma propriedade para eles. No exemplo acima, sabemos que arr é uma instância do objeto Array, por isso usamos Array.prototype para definir uma propriedade para Array. Mas e se não conhecêssemos a classe (protótipo) do ' arr'?

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

Como você pode ver, sem saber que ' arr' é uma matriz, podemos adicionar uma nova propriedade apenas referindo a classe de ' arr' usando 'arr.__proto__ '.

Acessamos o protótipo do ' arr' sem saber que é uma instância do Array e acho que foi o que o OP pediu.


A __proto__propriedade está obsoleta e quase não tem vantagem sobre a prototypepropriedade.
Sapphire_Brick
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.