Como obter uma class de object JavaScript?

Eu criei um object JavaScript, mas como posso determinar a class desse object?

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

Não há contrapartida exata para o getClass() do Java em JavaScript. Principalmente, isso se deve ao fato de o JavaScript ser uma linguagem baseada em protótipos , em vez de o Java ser baseado em classs .

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

  • typeof
  • instanceof
  • obj. constructor
  • func. prototype , proto . isPrototypeOf

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 das classs não globais. Para evitar isso, o Uglify tem um parâmetro --mangle que você pode definir como false usando gulp ou grunt .

 obj.constructor.name 

funciona na maioria dos casos em navegadores modernos, apesar de Function.name não ser oficialmente adicionado ao padrão até o ES6. Se o object for instanciado com var obj = new MyClass() , ele retornará “MyClass” como uma string.

Ele retornará “Número” para números, “Matriz” para matrizes e “Função” para funções, etc. Parece ser bastante confiável. Os únicos casos em que ele falha são se um object é criado sem um protótipo, via Object.create( null ) , ou o object foi instanciado de uma function anonimamente definida (sem nome).

Indiscutivelmente, o obj.constructor.name é muito mais intuitivo do que o typeof , e pode ser encapsulado em uma function para manipular o caso ímpar onde o constructor não está definido (e para tratar referências nulas).

Nota: Outra vantagem deste método é que ele trabalha intuitivamente nos limites do DOM versus comparar os objects do construtor diretamente ou usando instanceOf . A razão que não funciona como você pode esperar é que existem realmente diferentes instâncias da function construtora em cada DOM, portanto, fazer uma comparação de objects em seus construtores não funcionará.

Nota 2: Curiosamente, este método parece retornar o nome da function mais básica usada em uma cadeia de protótipos, o que infelizmente não é intuitivo. Por exemplo, se B derivar prototipicamente de A e você criar uma nova instância de B , b , b.constructor.name retornará “A”! Então isso parece totalmente para trás. Ele funciona bem para protótipos de nível único e todos os primitivos, no entanto.

Essa function retorna "undefined" , "null" ou a "class" em [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... 

Para obter a “pseudo class”, você pode obter a function de construtor, por

 obj.constructor 

assumindo que o constructor está configurado corretamente quando você faz a inheritance – que é algo como:

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

e estas duas linhas, junto com:

 var woofie = new Dog() 

fará com que woofie.constructor aponte para Dog . Observe que o Dog é uma function construtora e é um object Function . Mas você pode fazer if (woofie.constructor === Dog) { ... } .

Se você deseja obter o nome da class 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 à function de construtor, converte-o em string e extrai o nome da function de construtor.

Note que obj.constructor.name poderia ter funcionado bem, mas não é padrão. É no Chrome e no Firefox, mas não no IE, incluindo o IE 9 ou o IE 10 RTM.

Você pode obter uma referência para a function construtora que criou o object usando a propriedade constructor :

 function MyObject(){ } var obj = new MyObject(); obj.constructor; // MyObject 

Se você precisa confirmar o tipo de um object em tempo de execução, você pode usar o operador instanceof :

 obj instanceof MyObject // true 

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 class por tipo de input, se você não tiver uma instância de um object.

(escrito no ES2017)

notação de ponto também funciona bem

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

Eu encontro object.constructor.toString() return [object objectClass] no IE, em vez da function objectClass () {} retornada no chome. Então, eu 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 consertei o código da seguinte forma:

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

Para classs Javascript no ES6, você pode usar o object.constructor . Na class de exemplo abaixo, o método getClass() retorna a class ES6 como seria de esperar:

 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 class do método getClass , certifique-se de colocá-la entre colchetes, por exemplo: ruffles = new ( fluffy.getClass() )( args... );

Em javascript, não há classs, mas eu acho que você quer o nome do construtor e obj.constructor.toString() irá lhe dizer o que você precisa.

Concordo com dfa, é por isso que eu considero o prototye como a class quando nenhuma class nomeada é encontrada

Aqui está uma function 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; } 

De acordo com seu registro ininterrupto de compatibilidade com versões anteriores, o ECMAScript 6, JavaScript ainda não tem um tipo de class (embora nem todo mundo entenda isso). Ele tem uma palavra-chave class como parte de sua syntax de class para criar protótipos – mas ainda assim não é uma coisa chamada class . JavaScript não é agora e nunca foi uma linguagem clássica de OOP . Falar de JS em termos de class é apenas enganoso ou um sinal de ainda não estar gravando uma inheritance prototípica (apenas mantendo-a real).

Isso significa que este this.constructor ainda é uma ótima maneira de obter uma referência à function de constructor . E this.constructor.prototype é a maneira de acessar o próprio protótipo. Como isso não é Java, não é uma aula. É o object 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 o 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' 

Lá você tem isso! Em 2016, há uma palavra-chave de class em JavaScript, mas ainda não há um tipo de class. this.constructor é a melhor maneira de obter a function de construtor, this.constructor.prototype , a melhor maneira de obter access ao próprio protótipo.

Javascript é uma linguagem sem class: não há classs que definam o comportamento de uma class estaticamente como em Java. O JavaScript usa protótipos em vez de classs para definir as propriedades do object, incluindo methods e inheritance. É possível simular muitos resources baseados em class com protótipos em JavaScript.

Aqui está uma implementação de getClass() e getInstance()

Você pode obter uma referência para a class de um Objeto usando a window .

De um contexto de instância:

 function A() { this.getClass = function() { return window[this.constructor.name]; } this.getNewInstance = function() { return new window[this.constructor.name]; } } var a = new A(); console.log(a.getClass()); // function A { // etc... } // you can even: var b = new a.getClass(); b instanceof A; // true 

Do contexto estático:

 function B() {}; B.getClass = function() { return window[this.name]; } B.getInstance() { return new window[this.name]; } 

A pergunta parece ter sido respondida, mas o OP quer acessar a class de e object, assim como fazemos em Java e a resposta selecionada não é suficiente (imho).

Com a seguinte explicação, podemos obter uma class de um object (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 propriedade .last só estará disponível para o object ‘ arr ‘, que é instanciado a partir do protótipo Array. Assim, para que a propriedade .last esteja disponível para todos os objects instanciados do protótipo Array, temos que definir a propriedade .last 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 para qual tipo de object (protótipo) as variables ​​’ arr ‘ e ‘ arr2 ‘ pertencem! Em outras palavras, se você não souber o tipo de class (protótipo) do object ‘ arr ‘, não poderá definir uma propriedade para eles. No exemplo acima, sabemos que arr é a instância do object Array, é por isso que usamos Array.prototype para definir uma propriedade para Array. Mas e se não soubéssemos a class (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 ‘ é um Array, podemos adicionar uma nova propriedade apenas bu referindo a class do ‘ arr ‘ usando ‘ arr.__proto__ ‘.

Nós acessamos o protótipo do ‘ arr ‘ sem saber que é uma instância do Array e acho que foi isso que o OP pediu.