Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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.getOwnPropertyN

在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.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。。。好为什么不呢?