测试是否存在嵌套的JavaScript对象键

测试是否存在嵌套的JavaScript对象键,javascript,object,properties,nested,Javascript,Object,Properties,Nested,如果我对某个对象有引用: var test = {}; 可能(但不是立即)具有嵌套对象的对象,例如: {level1: {level2: {level3: "level3"}}}; 检查深度嵌套对象中是否存在属性的最佳方法是什么 警报(测试级别1)产生未定义,但发出警报(test.level1.level2.level3)失败 我目前正在做这样的事情: if(test.level1 && test.level1.level2 && test.level1.le

如果我对某个对象有引用:

var test = {};
可能(但不是立即)具有嵌套对象的对象,例如:

{level1: {level2: {level3: "level3"}}};
检查深度嵌套对象中是否存在属性的最佳方法是什么

警报(测试级别1)产生
未定义
,但发出
警报(test.level1.level2.level3)失败

我目前正在做这样的事情:

if(test.level1 && test.level1.level2 && test.level1.level2.level3) {
    alert(test.level1.level2.level3);
}
function checkNested(obj /*, level1, level2, ... levelN*/) {
  var args = Array.prototype.slice.call(arguments, 1);

  for (var i = 0; i < args.length; i++) {
    if (!obj || !obj.hasOwnProperty(args[i])) {
      return false;
    }
    obj = obj[args[i]];
  }
  return true;
}

var test = {level1:{level2:{level3:'level3'}} };

checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false
if (o(o(o(o(test).level1).level2).level3)
{

}
  const test = test?.level1?.level2?.level3;
  if (test) alert(test);
但是我想知道是否有更好的办法。

怎么样

try {
   alert(test.level1.level2.level3)
} catch(e) {
 ...whatever

}
怎么样

try {
   alert(test.level1.level2.level3)
} catch(e) {
 ...whatever

}

如果您不希望出现
类型错误
,则必须一步一步地执行此操作,因为如果其中一个成员为
null
未定义
,并且您尝试访问一个成员,将引发异常

您可以简单地
捕获
异常,或者创建一个函数来测试是否存在多个级别,如下所示:

if(test.level1 && test.level1.level2 && test.level1.level2.level3) {
    alert(test.level1.level2.level3);
}
function checkNested(obj /*, level1, level2, ... levelN*/) {
  var args = Array.prototype.slice.call(arguments, 1);

  for (var i = 0; i < args.length; i++) {
    if (!obj || !obj.hasOwnProperty(args[i])) {
      return false;
    }
    obj = obj[args[i]];
  }
  return true;
}

var test = {level1:{level2:{level3:'level3'}} };

checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false
if (o(o(o(o(test).level1).level2).level3)
{

}
  const test = test?.level1?.level2?.level3;
  if (test) alert(test);
但是,如果您希望获取嵌套属性的值,而不仅仅是检查其存在性,那么这里有一个简单的单行函数:

var o = function(obj) { return obj || {};};
函数getNested(obj,…args){
返回参数reduce((对象,级别)=>obj&&obj[level],obj)
}
常量测试={level1:{level2:{level3:'level3'}};
log(getNested(测试'level1','level2','level3');/'三级'
log(getNested(测试'level1','level2','level3','length');//6.
log(getNested(测试'level1','level2','foo');//未定义

log(getNested(测试'a','b');//未定义
如果您不希望出现
类型错误
,则必须一步一步地执行此操作,因为如果其中一个成员为
null
未定义
,并且您尝试访问一个成员,将引发异常

您可以简单地
捕获
异常,或者创建一个函数来测试是否存在多个级别,如下所示:

if(test.level1 && test.level1.level2 && test.level1.level2.level3) {
    alert(test.level1.level2.level3);
}
function checkNested(obj /*, level1, level2, ... levelN*/) {
  var args = Array.prototype.slice.call(arguments, 1);

  for (var i = 0; i < args.length; i++) {
    if (!obj || !obj.hasOwnProperty(args[i])) {
      return false;
    }
    obj = obj[args[i]];
  }
  return true;
}

var test = {level1:{level2:{level3:'level3'}} };

checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false
if (o(o(o(o(test).level1).level2).level3)
{

}
  const test = test?.level1?.level2?.level3;
  if (test) alert(test);
但是,如果您希望获取嵌套属性的值,而不仅仅是检查其存在性,那么这里有一个简单的单行函数:

var o = function(obj) { return obj || {};};
函数getNested(obj,…args){
返回参数reduce((对象,级别)=>obj&&obj[level],obj)
}
常量测试={level1:{level2:{level3:'level3'}};
log(getNested(测试'level1','level2','level3');/'三级'
log(getNested(测试'level1','level2','level3','length');//6.
log(getNested(测试'level1','level2','foo');//未定义

log(getNested(测试'a','b');//未定义
如果像字符串一样处理名称,则可以在任何深度读取对象属性:
't.level1.level2.level3'

window.t={level1:{level2:{level3: 'level3'}}};

function deeptest(s){
    s= s.split('.')
    var obj= window[s.shift()];
    while(obj && s.length) obj= obj[s.shift()];
    return obj;
}

alert(deeptest('t.level1.level2.level3') || 'Undefined');

它返回
undefined
如果任何段
未定义

您可以在任何深度读取对象属性,如果您像字符串一样处理名称:
't.level1.level2.level3'

window.t={level1:{level2:{level3: 'level3'}}};

function deeptest(s){
    s= s.split('.')
    var obj= window[s.shift()];
    while(obj && s.length) obj= obj[s.shift()];
    return obj;
}

alert(deeptest('t.level1.level2.level3') || 'Undefined');
如果任何段
未定义
,则返回
未定义

以下是模式I:

事实上,整篇文章讨论了如何使用javascript实现这一点。他决定使用上述语法(一旦你习惯了就不难理解)作为习语。

这里有一个模式I:


事实上,整篇文章讨论了如何使用javascript实现这一点。他决定将上述语法(一旦你习惯了就不难理解)作为一种习语使用。

一个简单的方法是:

try {
    alert(test.level1.level2.level3);
} catch(e) {
    alert("undefined");    // this is optional to put any output here
}

try/catch
捕获未定义任何更高级别对象(如test、test.level1、test.level1.level2)的情况。

一种简单的方法是:

try {
    alert(test.level1.level2.level3);
} catch(e) {
    alert("undefined");    // this is optional to put any output here
}

try/catch
捕获未定义任何更高级别对象(如test、test.level1、test.level1.level2)的情况。

一个简短的ES5版本@CMS的优秀答案:

// Check the obj has the keys in the order mentioned. Used for checking JSON results.  
var checkObjHasKeys = function(obj, keys) {
  var success = true;
  keys.forEach( function(key) {
    if ( ! obj.hasOwnProperty(key)) {
      success = false;
    }
    obj = obj[key];
  })
  return success;
}
通过类似的测试:

var test = { level1:{level2:{level3:'result'}}};
utils.checkObjHasKeys(test, ['level1', 'level2', 'level3']); // true
utils.checkObjHasKeys(test, ['level1', 'level2', 'foo']); // false

@CMS优秀答案的简短ES5版本:

// Check the obj has the keys in the order mentioned. Used for checking JSON results.  
var checkObjHasKeys = function(obj, keys) {
  var success = true;
  keys.forEach( function(key) {
    if ( ! obj.hasOwnProperty(key)) {
      success = false;
    }
    obj = obj[key];
  })
  return success;
}
通过类似的测试:

var test = { level1:{level2:{level3:'result'}}};
utils.checkObjHasKeys(test, ['level1', 'level2', 'level3']); // true
utils.checkObjHasKeys(test, ['level1', 'level2', 'foo']); // false
有一个函数将以安全的方式执行此操作。。。i、 e

safeRead(test, 'level1', 'level2', 'level3');
如果任何属性为null或未定义,则返回空字符串

有一个函数将以安全的方式执行此操作。。。i、 e

safeRead(test, 'level1', 'level2', 'level3');

如果任何属性为null或未定义,则返回一个空字符串

CMS给出的答案可以正常工作,并对null检查进行以下修改

function checkNested(obj /*, level1, level2, ... levelN*/) 
      {
             var args = Array.prototype.slice.call(arguments),
             obj = args.shift();

            for (var i = 0; i < args.length; i++) 
            {
                if (obj == null || !obj.hasOwnProperty(args[i]) ) 
                {
                    return false;
                }
                obj = obj[args[i]];
            }
            return true;
    }
函数checkNested(obj/*,level1,level2,…levelN*/)
{
var args=Array.prototype.slice.call(参数),
obj=args.shift();
对于(变量i=0;i
CMS给出的答案在对空检查进行以下修改后也可以正常工作

function checkNested(obj /*, level1, level2, ... levelN*/) 
      {
             var args = Array.prototype.slice.call(arguments),
             obj = args.shift();

            for (var i = 0; i < args.length; i++) 
            {
                if (obj == null || !obj.hasOwnProperty(args[i]) ) 
                {
                    return false;
                }
                obj = obj[args[i]];
            }
            return true;
    }
函数checkNested(obj/*,level1,level2,…levelN*/)
{
var args=Array.prototype.slice.call(参数),
obj=args.shift();
对于(变量i=0;i
以下选项从一开始就进行了详细阐述。两者的树相同:

var o = { a: { b: { c: 1 } } };

未定义时停止搜索
逐级保证
从一开始就详细阐述了以下选项。两者的树相同:

var o = { a: { b: { c: 1 } } };

未定义时停止搜索
逐级保证
我尝试了一种递归方法:

function objHasKeys(obj, keys) {
  var next = keys.shift();
  return obj[next] && (! keys.length || objHasKeys(obj[next], keys));
}
!keys.length | |
退出递归,因此它不会在没有键的情况下运行函数。测试:

obj = {
  path: {
    to: {
      the: {
        goodKey: "hello"
      }
    }
  }
}

console.log(objHasKeys(obj, ['path', 'to', 'the', 'goodKey'])); // true
console.log(objHasKeys(obj, ['path', 'to', 'the', 'badKey']));  // undefined
我正在使用它打印一组具有未知键/值的对象的友好html视图,例如:

var biosName = objHasKeys(myObj, 'MachineInfo:BiosInfo:Name'.split(':'))
             ? myObj.MachineInfo.BiosInfo.Name
             : 'unknown';

我尝试了一种递归方法:

function objHasKeys(obj, keys) {
  var next = keys.shift();
  return obj[next] && (! keys.length || objHasKeys(obj[next], keys));
}
!keys.length | |
退出递归,因此它不会在没有键的情况下运行函数。测试:

obj = {
  path: {
    to: {
      the: {
        goodKey: "hello"
      }
    }
  }
}

console.log(objHasKeys(obj, ['path', 'to', 'the', 'goodKey'])); // true
console.log(objHasKeys(obj, ['path', 'to', 'the', 'badKey']));  // undefined
我是你
o(o(o(o(o(test).level1).level2).level3, "none")
function validChain( object, ...keys ) {
    return keys.reduce( ( a, b ) => ( a || { } )[ b ], object ) !== undefined;
}

var test = {
  first: {
    second: {
        third: "This is not the key your are looking for"
    }
  }
}

if ( validChain( test, "first", "second", "third" ) ) {
    console.log( test.first.second.third );
}
var r1 = (((test || {}).level1 || {}).level2 || {}).level3;
var r2 = (((test || {}).level1 || {}).level2 || {}).foo;
var r1 = test.level1 && test.level1.level2 && test.level1.level2.level3;
var r2 = test.level1 && test.level1.level2 && test.level1.level2.foo;
function checkNested(obj) {
  for (var i = 1; i < arguments.length; i++) {
    if (!obj.hasOwnProperty(arguments[i])) {
      return false;
    }
    obj = obj[arguments[i]];
  }
  return true;
}
function get_if_exist(str) {
    try { return eval(str) }
    catch(e) { return undefined }
}
function validChain( object, ...keys ) {
    return keys.reduce( ( a, b ) => ( a || { } )[ b ], object ) !== undefined;
}
function objHasKeys(obj, keys) {
  var next = keys.shift();
  return obj[next] && (! keys.length || objHasKeys(obj[next], keys));
}
function nestedPropertyExists(obj, props) {
    var prop = props.shift();
    return prop === undefined ? true : obj.hasOwnProperty(prop) ? nestedPropertyExists(obj[prop], props) : false;
}
function deeptest(target, s){
    s= s.split('.')
    var obj= target[s.shift()];
    while(obj && s.length) obj= obj[s.shift()];
    return obj;
}
var o = function(obj) { return obj || {} };

var r1 = o(o(o(o(test).level1).level2).level3);
var r2 = o(o(o(o(test).level1).level2).foo);
function FetchKeys(obj) {
    let objKeys = [];
    let keyValues = Object.entries(obj);
    for (let i in keyValues) {
        objKeys.push(keyValues[i][0]);
        if (typeof keyValues[i][1] == "object") {
            var keys = FetchKeys(keyValues[i][1])
            objKeys = objKeys.concat(keys);
        }
    }
    return objKeys;
}

let test = { level1: { level2: { level3: "level3" } } };
let keyToCheck = "level2";
let keys = FetchKeys(test); //Will return an array of Keys

if (keys.indexOf(keyToCheck) != -1) {
    //Key Exists logic;
}
else {
    //Key Not Found logic;
}
const propExists = (obj, path) => {
    return !!path.split('.').reduce((obj, prop) => {
        return obj && obj[prop] ? obj[prop] : undefined;
    }, obj)
}
  const test = test?.level1?.level2?.level3;
  if (test) alert(test);
function getValue(object, path, fallback, fallbackOnFalsy) {
    if (!object || !path) {
        return fallback;
    }

    // Reduces object properties to the deepest property in the path argument.
    return path.split('.').reduce((object, property) => {
       if (object && typeof object !== 'string' && object.hasOwnProperty(property)) {
            // The property is found but it may be falsy.
            // If fallback is active for falsy values, the fallback is returned, otherwise the property value.
            return !object[property] && fallbackOnFalsy ? fallback : object[property];
        } else {
            // Returns the fallback if current chain link does not exist or it does not contain the property.
            return fallback;
        }
    }, object);
}
function getValue(o, path, fb, fbFalsy) {
   if(!o || !path) return fb;
   return path.split('.').reduce((o, p) => o && typeof o !== 'string' && o.hasOwnProperty(p) ? !o[p] && fbFalsy ? fb : o[p] : fb, o);
}
function getValue(o, path, fb) {
   if(!o || !path) return fb;
   return path.split('.').reduce((o, p) => o && typeof o !== 'string' && o.hasOwnProperty(p) ? o[p] : fb, o);
}
const obj = {
    c: {
        a: 2,
        b: {
            c: [1, 2, 3, {a: 15, b: 10}, 15]
        },
        c: undefined,
        d: null
    },
    d: ''
}
// null
console.log(getValue(obj, 'c.d', 'fallback'));

// array
console.log(getValue(obj, 'c.b.c', 'fallback'));

// array index 2
console.log(getValue(obj, 'c.b.c.2', 'fallback'));

// no index => fallback
console.log(getValue(obj, 'c.b.c.10', 'fallback'));
function ifSet(object, path) {
  return path.split('.').reduce((obj, part) => obj && obj[part], object)
}
let a = {b:{c:{d:{e:'found!'}}}}
ifSet(a, 'b.c.d.e') == 'found!'
ifSet(a, 'a.a.a.a.a.a') == undefined