Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是否可以获取对象的不可枚举继承属性名?_Javascript_Oop_Object_Properties - Fatal编程技术网

Javascript 是否可以获取对象的不可枚举继承属性名?

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.getOwnP

在JavaScript中,我们有几种获取对象属性的方法,具体取决于我们想要获取的内容

1)
Object.keys()
,它返回对象的所有自己的可枚举属性,即ECMA5方法

2) 一个
for…in
循环,返回对象的所有可枚举属性,无论它们是自己的属性还是从原型链继承的属性

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.getOwnPropertyNames(obj)
返回对象的所有自己的属性,无论是否可枚举

我们也有这样的方法,比如
hasOwnProperty(prop)
让我们检查属性是继承的还是实际上属于该对象,以及
propertyEnumerable(prop)
,顾名思义,它让我们检查属性是否可枚举

使用所有这些选项,无法获得对象的不可枚举、不可拥有的属性,这正是我想要做的。有没有办法做到这一点?换句话说,我能以某种方式获得继承的不可枚举属性的列表吗


谢谢。

要获取某些实例的所有继承属性或方法,您可以使用如下内容

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__"]

更新:稍微重构了代码(添加了空格和大括号,并改进了函数名):


这是我在研究这个课题时提出的解决方案。获取
obj
对象do
getProperties(obj,“nonown”、“nonenum”)的所有不可枚举的非自有属性

函数getProperties(对象、类型、可枚举性){ /** *返回对象属性的数组 *@param{String}type-属性类型。可以是“own”、“nonown”或“两者” *@param{String}可枚举性-属性可枚举性。可以是“enum”, *“非数值”或“两者” *@返回属性的{String | Array}数组 */ var props=Object.create(null);//字典 var firstIteration=true; 做{ var allProps=Object.getOwnPropertyNames(obj); var enumProps=Object.keys(obj); var nonenumProps=allProps.filter(x=>!(新集合(enumProps)).has(x)); enumProps.forEach(函数(prop){ 如果(!(道具中的道具)){ props[prop]={own:firstIteration,enum\uz:true}; } }); 非numprops.forEach(函数(prop){ 如果(!(道具中的道具)){ props[prop]={own:firstIteration,enum_2;:false}; } }); 第一次迭代=假; }while(obj=Object.getPrototypeOf(obj)); 用于(道具中的道具){ if(type==“own”&&props[prop][“own”]==false){ 删除道具[道具]; 继续; } if(type==“nonown”&&props[prop][“own”]==true){ 删除道具[道具]; 继续; } if(可枚举性==“枚举”&&props[prop][“枚举”]==false){ 删除道具[道具]; 继续; } if(可枚举性==“非数值”&&props[prop][“枚举”]==true){ 删除道具[道具]; } } 返回对象。键(道具); }
使用的示例:

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];
}
运行示例:

函数getAllPropertyNames(obj){ 让结果=新集合(); while(obj){ Object.getOwnPropertyNames(obj.forEach)(p=>result.add(p)); obj=Object.getPrototypeOf(obj); } 返回[…结果]; } 设obj={ abc:123, xyz:1.234, foobar:“你好” };
log(getAllPropertyNames(obj))我个人偏好中的一个实现:)


多亏了toby,我不明白的一点是:
while(curr=Object.getPrototypeOf(cure))
,因为条件语句使用赋值运算符而不是比较运算符,这不总是返回true吗?或者这一行实际上是在检查“curr”是否有原型?@AlexNabokov如果结果是falsy,它将返回false,这将在
Object时发生。getPrototypeOf(cure)
在原型链的顶部返回
null
。我猜这假设没有圆形原型链@Alex
Function.prototype
永远不能是“根”原型,因为它的prototype链接指向
Object.prototype
。函数
Object.getPrototypeOf(obj)
返回
obj
原型链中最顶层的对象。它使您能够遵循
obj
的原型链,直到到达其末端(
null
值)。我不确定你的问题是什么…@Alex不,它不是未定义的
Object.getPrototypeOf(John)
返回
Boy.prototype
对象(正如它应该的那样)-请参见此处:。请注意,构造函数
Boy
不在
John
的原型链中。
John
的原型链如下:
Boy.prototype->Object.prototype->null
“我认为Object.getPrototypeOf(obj)将返回obj的构造函数的原型”-是。对于
John
,他的构造函数是
Boy
,而
Boy
prototype
属性是
Boy.prototype
。所以
Object.getPrototypeOf(John)
返回
Boy.prototype
。您的问题回答了
function getAllPropertyNames(obj) {
    let result = new Set();
    while (obj) {
        Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
        obj = Object.getPrototypeOf(obj);
    }
    return [...result];
}
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);
}