簡體   English   中英

如何循環對象的javascript object並找到一個屬性

[英]How to loop javascript object of objects and find a property

我有一個樣本 object:

var test = {obj: check, oi: "5"  }        
var lord = {sol: "5"};
var holand = {vol: "try", mice: lord}
var second = {bol: "true"};
var check = { fol: holand}

我的問題是如何檢索 object“測試”是否具有“溶膠”屬性,該屬性位於另一個 object 幾層深處。 它應該是一個有點遞歸的 function 嗎? 如果 function 返回 true(屬性存在),是否可以檢索屬性的某種路徑。 在這種情況下,路徑應該是 test["obj"]["fol"]["mice"]

自從最初回答這個問題以來,我受到啟發去在圖書館工作以做到這一點: koalaesce

它的工作原理類似於:

 var test = { obj: check, oi: "5" } var lord = { sol: "5" }; var holand = { vol: "try", mice: lord } var second = { bol: "true" }; var check = { fol: holand } function getDescendent(base, steps) { var step = base; for (var i = 0; i < steps.length; ++i) { if (step.hasOwnProperty(steps[i])) { step = step[steps[i]]; } else { throw new Error("Missing link at " + steps[i]); } } return step; } document.write(getDescendent(check, ["fol", "mice", "sol"])); try { document.write(getDescendent(check, ["fol", "tofu", "sol"])); } catch (e) { document.write(e); } 

此處的算法從base對象開始,一直向下進行,遍歷代表每個步驟的屬性名稱的字符串數組。 它檢查以確保當前對象具有其自己的屬性( 不是繼承的屬性)並具有適當的名稱,然后向下移動到該級別。 如果對象不存在,則會拋出缺少的名稱。

在很多情況下,您可能希望刪除hasOwnProperty檢查,因為繼承/原型屬性和方法可能很有用(並且不會造成任何傷害)。 在您的情況下,使用簡單的對象,行為不會改變。 在大多數情況下, 檢查將允許您訪問更多屬性。

對於更聰明的ES6解決方案,您還可以使用reduce和:

let test = {
  obj: check,
  oi: "5"
}
let lord = {
  sol: "5"
};
let holand = {
  vol: "try",
  mice: lord
}
let second = {
  bol: "true"
};
let check = {
  fol: holand
}

function getDescendent(base, ...steps) {
  return steps.reduce((prev, cur) => {
    if (prev && prev.hasOwnProperty(cur)) {
      return prev[cur];
    } else {
      throw new Error("Missing link at " + cur);
    }
  }, base);
}

document.write(getDescendent(check, "fol", "mice", "sol"));
document.write(getDescendent(check, "fol", "tofu", "sol"));

您可以通過檢查對象的屬性來進行遞歸循環。 此線程描述如何檢查該屬性是否存在。

如何檢查對象在JavaScript中是否具有屬性?

是的,如果您想知道路徑,則在遞歸時必須保持跟蹤。

您必須有一個正確的想法要檢查什么。 即沿着對象層次結構的路徑。 因為如果您剛開始遞歸地迭代所有屬性(鍵),那么它一開始就沒有效率,並且很有可能進入循環引用。

不過,您可以查詢對象屬性,以及屬性的屬性。

/**
 * Get a property defined under given object's hierarchy, matching given path.
 * @param obj Object to look into.
 * @param path filesystem style path for properties. E.g '/prop1/prop2/prop3'
 * @returns {*} Property under object hierarchy, or undefined.
 */
function getProp(obj,path){
    var props = path.split('/').reverse();
    var p;
    var o = obj;
    while( p = props.pop()){
        o = o[p]; // you can use your preferred scope. i.e own property only
        if(o == undefined){
            return o;
        }
    }

    return o;
}

/**
 * Utility function to check if a property is defined under given object's hierarchy, matching given path.
 * @param obj Object to look into.
 * @param path filesystem style path for properties. E.g '/prop1/prop2/prop3'
 * @returns {boolean} true if property is defined, false if property is undefined.
 */
function hasProp(obj, path){
    return getProp(obj,path) != undefined;
}


// Test object
var testObj = {
                a:{
                    b:{
                        c:'hello',
                        d:{
                            e:'world'
                        }
                    }
                }
              };

// valid property paths
console.log(hasProp(testObj,'a/b/c/'));
console.log(hasProp(testObj,'a/b/d/e'));
console.log(getProp(testObj,'a/b/c/'));
console.log(getProp(testObj,'a/b/d/e'));

// invalid property paths
console.log(hasProp(testObj,'a/d/c/'));
console.log(hasProp(testObj,'a/b/d/e/f'));
console.log(getProp(testObj,'a/d/c/'));
console.log(getProp(testObj,'a/b/d/e/f'));

這是一種(大部分)純函數式方法,可以使用某種“條件”進行遞歸:

/**
    Recurse through object until condition is met.
    @param {Array} objs An array of objects
    @return {Boolean} Whether condition is met.
*/
const recurseObjs = (objs, condition) => {
    const _subObjs = []
    for (let obj of objs) {
        for (let val of Object.values(obj)) {
            if (val === condition /*replace with some condition or multiple*/) return true // Stop if your condition is found
            else if (typeof val === 'object' && val !== null && Object.prototype.toString.call(val) !== '[object Array]') _subObjs.push(val) // Else recurse through subobjects that are not array or null
        }
    }
    if (_subObjs.length > 0) return recurseObjs(_subObjs, condition); 
    return false // Default return value if condition not found
}

recurseObjs([{foo:'bar'},{hello:{cruel:'world'}}],'world') // => true
recurseObjs([{foo:'bar'},{hello:{cruel:'world'}}],'test') // => false

如果需要對象的“已找到”子屬性值的完整路徑,您可以創建一個新鍵值_parent以添加到子屬性 object。此_parent將是一個包含完整子屬性路徑的字符串。 在傳遞給回調 function 之前,它會在每次遞歸時更新。然后,可以返回_path而不是true條件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM