Javascript 是否可以获取对象的不可枚举继承属性名?
在JavaScript中,我们有几种获取对象属性的方法,具体取决于我们想要获取的内容 1 Object.keys,返回对象的所有自己的可枚举属性,ECMA5方法 2 for…in循环,返回对象的所有可枚举属性,无论它们是自己的属性还是从原型链继承的属性Javascript 是否可以获取对象的不可枚举继承属性名?,javascript,oop,object,properties,Javascript,Oop,Object,Properties,在JavaScript中,我们有几种获取对象属性的方法,具体取决于我们想要获取的内容 1 Object.keys,返回对象的所有自己的可枚举属性,ECMA5方法 2 for…in循环,返回对象的所有可枚举属性,无论它们是自己的属性还是从原型链继承的属性 function getAllProperties(obj){ var allProps = [] , curr = obj do{ var props = Object.getOwnPropertyN
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
}
3 Object.getOwnPropertyNamesobj,返回对象的所有自己的属性,无论是否可枚举
我们也有这样的方法,比如hasOwnPropertyprop让我们检查属性是继承的还是实际属于该对象,propertyIsEnumerableprop,顾名思义,它让我们检查属性是否可枚举
有了所有这些选项,就无法获得对象的不可枚举、非自有属性,这正是我想要做的。有没有办法做到这一点?换句话说,我能以某种方式获得继承的不可枚举属性的列表吗
谢谢。要获取某些实例的所有继承属性或方法,您可以使用如下内容
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(","));
由于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;
}
这是我在研究这个课题时提出的解决方案。要获取obj对象的所有不可枚举的非自有属性,请执行getPropertiesobj、nonown、nonenum 函数getPropertiesobj,类型,可枚举性{ /** *返回对象属性的数组 *@param{String}type-属性类型。可以是own、nonown或两者兼有 *@param{String}可枚举性-属性可枚举性。可以是enum, *非数值或两者都有 *@返回属性的{String | Array}数组 */ var props=Object.createnull;//字典 var firstIteration=true; 做{ var allProps=Object.getOwnPropertyNamesobj; var enumProps=Object.keysobj; var nonenumProps=allProps.filterx=>!新建SetenumProps.hasx; enumProps.forEachfunctionprop{ 如果!用道具支撑{ props[prop]={own:firstIteration,enum\uz:true}; } }; nonenumProps.forEachfunctionprop{ 如果!用道具支撑{ props[prop]={own:firstIteration,enum_2;:false}; } }; 第一次迭代=假; }而obj=Object.getPrototypeOfObject; 道具中的道具{ 如果type==own&&props[prop][own]==false{ 删除道具[道具]; 持续 } 如果type==nonown&&props[prop][own]==true{ 删除道具[道具]; 持续 } 如果可枚举性==enum&&props[prop][enum_z]==false{ 删除道具[道具]; 持续 } 如果可枚举性==nonenum&&props[prop][enum_z]==true{ 删除道具[道具]; } } 返回Object.keysprops; } 使用的示例:
function MakeA(){
}
var a = new MakeA();
var arNonEnumerable = getNonEnumerableNonOwnPropertyNames(a);
如果您试图记录父对象的不可枚举属性,例如,默认情况下,es6中类内定义的方法在prototype上设置,但设置为不可枚举
Object.getOwnPropertyNames(Object.getPrototypeOf(obj));
IMO说,利用Sets可以得到一个更干净的解决方案
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);
}
使用递归的更干净的解决方案:
function getAllPropertyNames (obj) {
const proto = Object.getPrototypeOf(obj);
const inherited = (proto) ? getAllPropertyNames(proto) : [];
return [...new Set(Object.getOwnPropertyNames(obj).concat(inherited))];
}
编辑
更通用的功能:
function walkProtoChain (obj, callback) {
const proto = Object.getPrototypeOf(obj);
const inherited = (proto) ? walkProtoChain(proto, callback) : [];
return [...new Set(callback(obj).concat(inherited))];
}
function getOwnNonEnumPropertyNames (obj) {
return Object.getOwnPropertyNames(obj)
.filter(p => !obj.propertyIsEnumerable(p));
}
function getAllPropertyNames (obj) {
return walkProtoChain(obj, Object.getOwnPropertyNames);
}
function getAllEnumPropertyNames (obj) {
return walkProtoChain(obj, Object.keys);
}
function getAllNonEnumPropertyNames (obj) {
return walkProtoChain(obj, getOwnNonEnumPropertyNames);
}
可以使用Object.getOwnPropertySymbols等应用相同的模板。在ES6中直接迭代:
function getAllPropertyNames(obj) {
let result = new Set();
while (obj) {
Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
obj = Object.getPrototypeOf(obj);
}
return [...result];
}
运行示例:
函数getAllPropertyNamesobj{
让结果=新集合;
而obj{
Object.getOwnPropertyNamesobj.forEachp=>result.addp;
obj=Object.getPrototypeOfobj;
}
返回[…结果];
}
设obj={
abc:123,
xyz:1.234,
福巴:你好
};
console.loggetAllPropertyNamesobj 我个人偏好的实现:
function getAllProperties(In, Out = {}) {
const keys = Object.getOwnPropertyNames(In);
keys.forEach(key => Object.defineProperty(In, key, {
enumerable: true
}));
Out = { ...In, ...Out };
const Prototype = Object.getPrototypeOf(In);
return Prototype === Object.prototype ? Out : getAllProperties(Proto, Out);
}
多亏了toby,有一点我不明白:whilecurr=Object.getPrototypeOfcure,因为条件语句使用赋值运算符而不是比较运算符,这不总是返回true吗?或者这一行实际上是在检查curr是否有原型?@AlexNabokov如果结果是falsy,它将返回false,这将发生在Object.getPrototypeOfcure在原型链的顶部返回null时。我猜这假设没有圆形原型链@Alex Function.prototype永远不能是根prototype,因为它的prototype链接指向Object.prototype。函数Object.getPrototypeOf obj返回obj原型链中最顶层的对象。它使您能够遵循obj的原型链,直到您到达其末端空值。我不确定你的问题是什么…@Alex不,这不是未定义的。Object.getPrototypeOfJohn返回Boy.prototype对象,正如它应该返回的那样-请参见此处:。请注意,构造函数男孩不是
在约翰的原型链中。John的原型链如下:Boy.prototype->Object.prototype->null。我以为Object.getPrototypeObj将返回obj的构造函数的原型-是的。在John的例子中,他的构造函数是Boy,Boy的prototype属性是Boy.prototype。所以Object.getPrototypeOfJohn返回Boy.prototype。你的问题回答了我要问的问题:如何检查不可枚举的属性,只是为了探索预定义对象中可用的内容。终于找到了getOwnPropertyNames!:-@马卡斯:-这就是所谓的一切!最好使用Object.getInherited而不是Object.prototype.getInherited。这样做也消除了对丑陋的人的需求!name==“getInherited”检查。此外,在您的实现中,props数组可以包含重复的属性。最后,忽略构造函数属性的目的是什么?object.getInherited何时变为true?请检查下面的问题,因为我一直在继承:IMHO-这些属于反射,而不是对象。或者-或者-我希望从language Object.keysrc,[settings]中,可选设置可以指定是否包含非九位数、是否包含继承、是否包含非枚举继承、是否包含自己、是否包含符号,以及可能要挖掘的最大继承深度。呃。。。Object.entries也一样。但不确定Object.values。。。好为什么不呢?