recorrer objetos objeto metodos lista keys eliminar elemento array agregar javascript oop object properties

javascript - objetos - ¿Es posible obtener los nombres de propiedades heredadas no enumerables de un objeto?



object.keys map (6)

Aprovechando Sets conduce a una solución algo más limpia, IMO.

const own = Object.getOwnPropertyNames; const proto = Object.getPrototypeOf; function getAllPropertyNames(obj) { const props = new Set(); do own(obj).forEach(p => props.add(p)); while (obj = proto(obj)); return Array.from(props); }

En JavaScript tenemos algunas formas de obtener las propiedades de un objeto, dependiendo de lo que queremos obtener.

1) Object.keys() , que devuelve todas las propiedades enumerables propias de un objeto, un método ECMA5.

2) a for...in loop, que devuelve todas las propiedades enumerables de un objeto, independientemente de si son propiedades propias o heredadas de la cadena de prototipos.

3) Object.getOwnPropertyNames(obj) que devuelve todas las propiedades propias de un objeto, enumerable o no.

También tenemos métodos como hasOwnProperty(prop) nos permite verificar si una propiedad es heredada o realmente pertenece a ese objeto, y propertyIsEnumerable(prop) que, como su nombre lo sugiere, nos permite verificar si una propiedad es enumerable.

Con todas estas opciones, no hay forma de obtener una propiedad no enumerable ni propiedad de un objeto, que es lo que quiero hacer. ¿Hay alguna manera de hacer esto? En otras palabras, ¿puedo de alguna manera obtener una lista de las propiedades no enumerables heredadas?

Gracias.


Aquí está la solución que se me ocurrió mientras estudiaba el tema. Para obtener todas las propiedades del objeto obj no son enumerables y no enumerables getProperties(obj, "nonown", "nonenum");

function getProperties(obj, type, enumerability) { /** * Return array of object properties * @param {String} type - Property type. Can be "own", "nonown" or "both" * @param {String} enumerability - Property enumerability. Can be "enum", * "nonenum" or "both" * @returns {String|Array} Array of properties */ var props = Object.create(null); // Dictionary var firstIteration = true; do { var allProps = Object.getOwnPropertyNames(obj); var enumProps = Object.keys(obj); var nonenumProps = allProps.filter(x => !(new Set(enumProps)).has(x)); enumProps.forEach(function(prop) { if (!(prop in props)) { props[prop] = { own: firstIteration, enum_: true }; } }); nonenumProps.forEach(function(prop) { if (!(prop in props)) { props[prop] = { own: firstIteration, enum_: false }; } }); firstIteration = false; } while (obj = Object.getPrototypeOf(obj)); for (prop in props) { if (type == "own" && props[prop]["own"] == false) { delete props[prop]; continue; } if (type == "nonown" && props[prop]["own"] == true) { delete props[prop]; continue; } if (enumerability == "enum" && props[prop]["enum_"] == false) { delete props[prop]; continue; } if (enumerability == "nonenum" && props[prop]["enum_"] == true) { delete props[prop]; } } return Object.keys(props); }


Dado que getOwnPropertyNames puede obtenerle propiedades no enumerables, puede usar eso y combinarlo con subir la cadena del prototipo.

function getAllProperties(obj){ var allProps = [] , curr = obj do{ var props = Object.getOwnPropertyNames(curr) props.forEach(function(prop){ if (allProps.indexOf(prop) === -1) allProps.push(prop) }) }while(curr = Object.getPrototypeOf(curr)) return allProps }

Lo probé en Safari 5.1 y obtuve

> getAllProperties([1,2,3]) ["0", "1", "2", "length", "constructor", "push", "slice", "indexOf", "sort", "splice", "concat", "pop", "unshift", "shift", "join", "toString", "forEach", "reduceRight", "toLocaleString", "some", "map", "lastIndexOf", "reduce", "filter", "reverse", "every", "hasOwnProperty", "isPrototypeOf", "valueOf", "__defineGetter__", "__defineSetter__", "__lookupGetter__", "propertyIsEnumerable", "__lookupSetter__"]

Actualización: refactorizó el código un poco (agregó espacios y llaves y mejoró el nombre de la función):

function getAllPropertyNames( obj ) { var props = []; do { Object.getOwnPropertyNames( obj ).forEach(function ( prop ) { if ( props.indexOf( prop ) === -1 ) { props.push( prop ); } }); } while ( obj = Object.getPrototypeOf( obj ) ); return props; }

Y simplemente obtener todo ... (enum / nonenum, self / inherited ... Por favor confirme ...

function getAllPropertyNames( obj ) { var props = []; do { props= props.concat(Object.getOwnPropertyNames( obj )); } while ( obj = Object.getPrototypeOf( obj ) ); return props; }


Para obtener todas las propiedades o métodos heredados para alguna instancia, podrías usar algo como esto

var BaseType = function () { this.baseAttribute = "base attribute"; this.baseMethod = function() { return "base method"; }; }; var SomeType = function() { BaseType(); this.someAttribute = "some attribute"; this.someMethod = function (){ return "some method"; }; }; SomeType.prototype = new BaseType(); SomeType.prototype.constructor = SomeType; var instance = new SomeType(); Object.prototype.getInherited = function(){ var props = [] for (var name in this) { if (!this.hasOwnProperty(name) && !(name == ''constructor'' || name == ''getInherited'')) { props.push(name); } } return props; }; alert(instance.getInherited().join(","));


si está intentando registrar propiedades no enumerables de un objeto primario, por ejemplo. de manera predeterminada, los métodos definidos dentro de una clase en es6 se configuran en prototipo, pero se configuran como no enumerables.

Object.getOwnPropertyNames(Object.getPrototypeOf(obj));


function getNonEnumerableNonOwnPropertyNames( obj ) { var oCurObjPrototype = Object.getPrototypeOf(obj); var arReturn = []; var arCurObjPropertyNames = []; var arCurNonEnumerable = []; while (oCurObjPrototype) { arCurObjPropertyNames = Object.getOwnPropertyNames(oCurObjPrototype); arCurNonEnumerable = arCurObjPropertyNames.filter(function(item, i, arr){ return !oCurObjPrototype.propertyIsEnumerable(item); }) Array.prototype.push.apply(arReturn,arCurNonEnumerable); oCurObjPrototype = Object.getPrototypeOf(oCurObjPrototype); } return arReturn; }

Ejemplo de uso:

function MakeA(){ } var a = new MakeA(); var arNonEnumerable = getNonEnumerableNonOwnPropertyNames(a);