如何检查对象或其子/子对象在Javascript中是否具有属性/键?

时间:2021-10-14 21:20:26

What I am looking for is basically a hasOwnProperty() or 'in' function which is recursive and looks down the chain to see if a key or property exists in an object.

我正在寻找的基本上是一个hasOwnProperty()或'in'函数,它是递归的,并向下看链以查看对象中是否存在键或属性。

For example I have the object:

例如,我有对象:

var user = {
  username: "Derpette",
  profile: {
    role: 'admin',
    sex: 'female',
    emails:['derpette42@derpmail.com']
    }
}

I want to know if there is a key/property 'role' anywhere in the object or its sub-objects. So I want to be able to call something like user.hasProperty('role') and it would return true.

我想知道对象或其子对象中的任何位置是否存在键/属性“角色”。所以我希望能够调用user.hasProperty('role')这样的东西,它会返回true。

Right now I am using if statements with a chain of assertions to check but it doesn't seem clean, especially for deep nested properties.

现在我正在使用带有断言链的if语句进行检查,但它看起来并不干净,特别是对于深层嵌套属性。

For example I would do:

例如,我会这样做:

if(user && user.profile && user.profile.role){
    //Manipulate/Use user.profile.role here
}

Another example of a use-case for this is if I am filtering mongoDB update modifiers coming from a client. I want to make sure they aren't updating their own role so I need to check that the property 'role' isn't somewhere in their mongoDB modifier json object. But it could be in a few places in a modifier so doing the if property chaining doesn't work well for this case.

另一个用例的例子是我是否正在过滤来自客户端的mongoDB更新修饰符。我想确保他们没有更新自己的角色,所以我需要检查属性'role'不在他们的mongoDB修饰符json对象中。但它可能位于修饰符中的一些位置,因此执行if属性链接对于此情况不起作用。

Do I need to write my own recursive hasOwnProperty? I am thinking that something like this should already exist somewhere in a project like jquery or underscores.js or sugar.js but I can't seem to find it.

我是否需要编写自己的递归hasOwnProperty?我认为像这样的东西应该已经存在于像jquery或underscores.js或sugar.js这样的项目中,但我似乎无法找到它。

2 个解决方案

#1


3  

You could do this recursively:

你可以递归地做到这一点:

function recHasProp(obj, prop) {
    for (var p in obj) {
        if (obj.hasOwnProperty(p)) {
            if (p === prop) {
                return obj;
            } else if (obj[p] instanceof Object && recHasProp(obj[p], prop)) {
                return obj[p];
            }
        }
    }
    return null;
}

Usage:

var obj = recHasProp(user, 'role');
if (obj) {
    // obj.role exists, and obj is user or a child of user
}

#2


2  

My take on this, it's not pretty, but it's very performant in the few lines that it is.

我对此有所了解,它并不漂亮,但它在几条线上非常高效。

function hasProp(obj, propPath, i) {
      if (typeof(i) === 'undefined' && !(i=0)) {
        propPath = propPath.split('.');
      }
      if (typeof(obj[propPath[i]]) !== 'undefined') {
        return (++i && i !== propPath.length) ? hasProp(obj[propPath[i - 1]], propPath, i) : true;
      }
      return false;
};

Usage Example (in your case):

用法示例(在您的情况下):

hasProp(user, 'profile.role');

Plunker: http://plnkr.co/edit/CIePivi3XcTEugFzEUyt?p=preview

#1


3  

You could do this recursively:

你可以递归地做到这一点:

function recHasProp(obj, prop) {
    for (var p in obj) {
        if (obj.hasOwnProperty(p)) {
            if (p === prop) {
                return obj;
            } else if (obj[p] instanceof Object && recHasProp(obj[p], prop)) {
                return obj[p];
            }
        }
    }
    return null;
}

Usage:

var obj = recHasProp(user, 'role');
if (obj) {
    // obj.role exists, and obj is user or a child of user
}

#2


2  

My take on this, it's not pretty, but it's very performant in the few lines that it is.

我对此有所了解,它并不漂亮,但它在几条线上非常高效。

function hasProp(obj, propPath, i) {
      if (typeof(i) === 'undefined' && !(i=0)) {
        propPath = propPath.split('.');
      }
      if (typeof(obj[propPath[i]]) !== 'undefined') {
        return (++i && i !== propPath.length) ? hasProp(obj[propPath[i - 1]], propPath, i) : true;
      }
      return false;
};

Usage Example (in your case):

用法示例(在您的情况下):

hasProp(user, 'profile.role');

Plunker: http://plnkr.co/edit/CIePivi3XcTEugFzEUyt?p=preview