Можно ли получить не перечислимые наследуемые имена свойств объекта?
в JavaScript у нас есть несколько способов получения свойств объекта, в зависимости от того, что мы хотим получить.
1) Object.keys()
, который возвращает все собственные, перечислимые свойства объекта, метод ECMA5.
2) a for...in
цикл, который возвращает все перечислимые свойства объекта, независимо от того, являются ли они собственными свойствами или унаследованы от цепочки прототипов.
3) Object.getOwnPropertyNames(obj)
, который возвращает все собственные свойства объекта, перечисляемую или не.
у нас также есть такие методы, как hasOwnProperty(prop)
позволяет проверить, если свойство наследуется или на самом деле принадлежит этому объекту, и propertyIsEnumerable(prop)
который, как следует из названия, позволяет нам проверить, является ли свойство перечислимым.
со всеми этими опциями, нет никакого способа, чтобы получить не перечислимый, не собственный свойство объекта, что я и хочу сделать. Есть ли способ сделать это? Другими словами, могу ли я каким-то образом получить список унаследованных не перечислимых недвижимость?
спасибо.
6 ответов:
С
getOwnPropertyNames
может получить вам не перечислимые свойства, вы можете использовать это и объединить его с ходьбой по цепочке прототипов.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 }
Я проверил это на Safari 5.1 и получил
> 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__"]
обновление: немного изменил код (добавил пробелы и фигурные скобки, а также улучшил имя функции):
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; }
и просто получить все..(enum / nonenum, self / inherited.. пожалуйста утвердить..
function getAllPropertyNames( obj ) { var props = []; do { props= props.concat(Object.getOwnPropertyNames( obj )); } while ( obj = Object.getPrototypeOf( obj ) ); return props; }
чтобы получить все унаследованные свойства или методы для некоторого экземпляра, вы можете использовать что-то вроде этого
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(","));
вот решение, которое я придумал во время изучения предмета. Чтобы получить все не перечислимые не-собственные свойства
obj
объект dogetProperties(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); }
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; }
пример использования:
function MakeA(){ } var a = new MakeA(); var arNonEnumerable = getNonEnumerableNonOwnPropertyNames(a);
Если вы пытаетесь зарегистрировать не перечислимые свойства родительского объекта ex. по умолчанию методы, определенные внутри класса в es6, устанавливаются на prototype, но задаются как не перечислимые.
Object.getOwnPropertyNames(Object.getPrototypeOf(obj));
использование наборов приводит к несколько более чистому решению, 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); }