recorrer - ¿Cómo obtener una clase de objeto JavaScript?
object.values javascript (14)
Creé un objeto de JavaScript, pero ¿cómo puedo determinar la clase de ese objeto?
Quiero algo similar al método .getClass()
Java.
Aquí hay una implementación de getClass()
y getInstance()
Puede obtener una referencia para una clase de Objeto usando la window
.
Desde un contexto de instancia:
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
Del contexto estático:
function B() {};
B.getClass = function() {
return window[this.name];
}
B.getInstance() {
return new window[this.name];
}
De acuerdo con su registro ininterrumpido de compatibilidad con versiones anteriores, ECMAScript 6, JavaScript aún no tiene un tipo de class
(aunque no todos lo entienden). Tiene una palabra clave de class
como parte de su sintaxis de class
para crear prototipos, pero todavía no hay nada llamado clase . JavaScript no es ahora y nunca ha sido un lenguaje OOP clásico . Hablar de JS en términos de clase es solo engañoso o un signo de no poseer aún una herencia prototípica (solo mantenerla real).
Eso significa que this.constructor
sigue siendo una excelente manera de obtener una referencia a la función constructor
. Y this.constructor.prototype
es la forma de acceder al prototipo en sí. Como esto no es Java, no es una clase. Es el objeto prototipo desde el que se instaló la instancia. Aquí hay un ejemplo que utiliza el azúcar sintáctico ES6 para crear una cadena de prototipo:
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)
Esto es lo que produce 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''
¡Ahí tienes! En 2016, hay una palabra clave de class
en JavaScript, pero aún no hay ningún tipo de clase. this.constructor
es la mejor manera de obtener la función de constructor, this.constructor.prototype
la mejor manera de obtener acceso al prototipo en sí.
En javascript, no hay clases, pero creo que quieres que el nombre del constructor y obj.constructor.toString()
te digan lo que necesitas.
Encuentro object.constructor.toString()
devuelve [object objectClass]
en IE, en lugar de la function objectClass () {}
devuelta en chome. Por lo tanto, creo que el código en http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects puede no funcionar bien en IE. Y arreglé el código de la siguiente manera:
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;
};
Esta función devuelve "undefined"
, "null"
o la "class"
en [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...
Estoy de acuerdo con dfa, por eso considero que el prototye es la clase cuando no se encuentra una clase con nombre
Aquí hay una función mejorada de la publicada por Eli Gray, para que coincida con mi 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;
}
Javascript es un lenguaje sin clases: no hay clases que definan el comportamiento de una clase de forma estática como en Java. JavaScript usa prototipos en lugar de clases para definir las propiedades de los objetos, incluidos los métodos y la herencia. Es posible simular muchas características basadas en clase con prototipos en JavaScript.
La pregunta parece ya contestada, pero el OP quiere acceder a la clase y al objeto, al igual que nosotros en Java y la respuesta seleccionada no es suficiente (imho).
Con la siguiente explicación, podemos obtener una clase de un objeto (en realidad se llama prototipo en JavaScript).
var arr = new Array(''red'', ''green'', ''blue'');
var arr2 = new Array(''white'', ''black'', ''orange'');
Puedes agregar una propiedad como esta:
Object.defineProperty(arr,''last'', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
Pero la propiedad .last
solo estará disponible para el objeto '' arr
'', que se crea desde el prototipo Array. Por lo tanto, para que la propiedad .last
esté disponible para todos los objetos instanciados desde el prototipo Array, tenemos que definir la propiedad .last
para el prototipo Array:
Object.defineProperty(Array.prototype,''last'', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
El problema aquí es que debes saber a qué tipo de objeto (prototipo) pertenecen las variables '' arr
'' y '' arr2
''. En otras palabras, si no conoce el tipo de clase (prototipo) del objeto '' arr
'', entonces no podrá definir una propiedad para ellos. En el ejemplo anterior, sabemos que arr es una instancia del objeto Array, por eso usamos Array.prototype para definir una propiedad para Array. Pero, ¿y si no conociéramos la clase (prototipo) del '' arr
''?
Object.defineProperty(arr.__proto__,''last2'', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
Como puede ver, sin saber que '' arr
'' es un Array, podemos agregar una nueva propiedad simplemente refiriendo la clase de '' arr
'' usando '' arr.__proto__
''.
Accedimos al prototipo del '' arr
'' sin saber que es una instancia de Array y creo que eso es lo que pidió OP.
No hay una contraparte exacta de getClass()
de Java en JavaScript. Esto se debe principalmente a que JavaScript es un lenguaje basado en prototipos , a diferencia de Java como uno class-based .
Dependiendo de para qué necesite getClass()
, hay varias opciones en JavaScript:
-
typeof
-
instanceof
-
obj.
constructor
-
func.
prototype
,proto
.isPrototypeOf
Algunos ejemplos:
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: si está compilando su código con Uglify, cambiará los nombres de clase no globales. Para evitar esto, Uglify tiene un --mangle
que puede establecer en falso usando gulp o grunt .
Para las clases de Javascript en ES6 puede usar object.constructor
. En la clase de ejemplo a continuación, el método getClass()
devuelve la clase ES6 como cabría 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!"
Si getClass
instancia de la clase desde el método getClass
, asegúrese de envolverla entre paréntesis, por ejemplo, ruffles = new ( fluffy.getClass() )( args... );
Para obtener la "pseudo clase", puede obtener la función de constructor, mediante
obj.constructor
asumiendo que el constructor
está configurado correctamente cuando haces la herencia, que es por algo como:
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
Y estas dos líneas, junto con:
var woofie = new Dog()
Hará que woofie.constructor
apunte a Dog
. Tenga en cuenta que Dog
es una función constructora, y es un objeto Function
. Pero puedes hacerlo if (woofie.constructor === Dog) { ... }
.
Si desea obtener el nombre de la clase como una cadena, encontré que lo siguiente funciona 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;
}
Llega a la función constructora, la convierte en cadena y extrae el nombre de la función constructora.
Tenga en cuenta que obj.constructor.name
podría haber funcionado bien, pero no es estándar. Está en Chrome y Firefox, pero no en IE, incluidos IE 9 o IE 10 RTM.
Puede obtener una referencia a la función constructora que creó el objeto utilizando la propiedad constructora :
function MyObject(){
}
var obj = new MyObject();
obj.constructor; // MyObject
Si necesita confirmar el tipo de un objeto en tiempo de ejecución, puede usar el operador instanceof :
obj instanceof MyObject // true
Tuve una situación para trabajar genérico ahora y usé esto:
class Test {
// your class definition
}
nameByType = function(type){
return type.prototype["constructor"]["name"];
};
console.log(nameByType(Test));
esa es la única manera que encontré para obtener el nombre de clase por tipo de entrada si no tiene una instancia de un objeto.
(Escrito en ES2017)
la notación de puntos también funciona bien
console.log(Test.prototype.constructor.name); // returns "Test"
obj.constructor.name
funciona en la mayoría de los casos en los navegadores modernos, a pesar de que Function.name
no se agregó oficialmente a la norma hasta ES6. Si se crea una instancia del objeto con var obj = new MyClass()
, devolverá "MyClass" como una cadena.
Devolverá "Número" para números, "Array" para matrices y "Función" para funciones, etc. Parece ser bastante confiable. Los únicos casos en los que falla son si un objeto se crea sin un prototipo, a través de Object.create( null )
, o si se creó una instancia del objeto desde una función definida anónimamente (sin nombre).
Podría decirse que obj.constructor.name
es mucho más intuitivo que typeof
, y podría ser encapsulado en una función para manejar el caso impar donde el constructor
no está definido (y para manejar referencias nulas).
Nota: Otra ventaja de este método es que funciona de manera intuitiva a través de los límites del DOM en comparación con los objetos del constructor directamente o mediante el uso de instanceOf
. La razón por la que no funciona como podría esperarse es que en realidad hay diferentes instancias de la función de constructor en cada DOM, por lo que no funciona una comparación de objetos en sus constructores.
Nota 2: Por extraño que parezca, este método parece devolver el nombre de la función más básica utilizada en una cadena de prototipo, que desafortunadamente no es intuitiva. Por ejemplo, si B
deriva prototípicamente de A
y crea una nueva instancia de B
, b
, b.constructor.name
devuelve "A"! Así que eso se siente totalmente al revés. Sin embargo, funciona bien para prototipos de un solo nivel y todos los primitivos.