Vyhledávání na webu

Javascript objekty: získat rodiče


Mám následující (vložený) objekt:

obj: { subObj: { foo: 'hello world' } };

Další věc, kterou udělám, je odkazovat na subobjekt takto:

var s = obj.subObj;

Teď bych chtěl získat odkaz na objekt obj ze proměnné s. Něco jako:

var o = s.parent;

Je to nějak možné?

Odpověď č. 1

Vnořený objekt (dítě) uvnitř jiného objektu (rodič) nemůže získat data přímo od svého rodiče.

Podívej se na toto:

var main = {
    name : "main object",
    child : {
        name : "child object"
    }
};

Pokud se zeptáte hlavního objektu, jaké je jméno jeho dítěte (main.child.name), dostanete ho.
Naopak to udělat nemůžete, protože dítě neví, kdo je jeho rodič.
(Můžete získat main.name, ale nedostanete main.child.parent.name).

Mimochodem, funkce by mohla být užitečná k vyřešení této nápovědy.
Rozšiřme kód výše:

var main = {
    name : "main object",
    child : {
        name : "child object"
    },
    init : function() {
        this.child.parent = this;
        delete this.init;
        return this;
    }
}.init();

Uvnitř funkce init můžete získat nadřazený objekt jednoduše zavoláním this.
Takže definujeme vlastnost parent přímo uvnitř objektu child.
Poté (volitelně) můžeme odstranit metodu init.
Nakonec vrátíme hlavní objekt jako výstup z funkce init.

Pokud se nyní pokusíte získat main.child.parent.name, dostanete to správně.
Je to trochu složité, ale funguje to dobře.

Odpověď č. 2

Ne. Není možné vědět, z jakého objektu pochází.

s a obj.subObj mají oba jednoduše odkazy na stejný objekt.

Můžete také udělat:

var obj = { subObj: {foo: 'hello world'} };
var obj2 = {};
obj2.subObj = obj.subObj;
var s = obj.subObj;

Nyní máte tři reference, obj.subObj, obj2.subObj a s, na stejný objekt. Žádná z nich není speciální.

Odpověď č. 3

Toto je stará otázka, ale když jsem na ni narazil při hledání odpovědi, myslel jsem si, že přidám svou odpověď, abych pomohl ostatním, jakmile budou mít stejný problém.

Mám strukturu takto:

var structure = {
    "root":{
        "name":"Main Level",
        nodes:{
            "node1":{
                "name":"Node 1"  
            },
            "node2":{
                "name":"Node 2"  
            },
            "node3":{
                "name":"Node 3"  
            }
        }
    }
}

Momentálně nevím, jak získat nadřazený uzel s jeho hodnotou názvu „Hlavní úroveň“, když odkážu na jeden z poduzlů.

Nyní představuji rekurzivní funkci, která prochází strukturu a přidává každému objektu uzlu atribut parent a vyplňuje ho jeho rodičem takto.

var setParent = function(o){
     if(o.nodes != undefined){
          for(n in o.nodes){
              o.nodes[n].parent = o;
              setParent(o.nodes[n]);
          }
     }
}

Pak jen zavolám tuto funkci a nyní mohu získat rodiče aktuálního uzlu v tomto objektovém stromě.

setParent(structure.root);

Pokud nyní mám odkaz na druhý poduzel root, mohu jen zavolat.

var node2 = structure.root.nodes["node2"];
console.log(node2.parent.name);

a zobrazí „Hlavní úroveň“.

Doufám, že to pomůže..

Odpověď č. 4

Mnoho odpovědí zde zahrnuje procházení objektu a „manuální“ (i když programově) vytváření rodičovské vlastnosti, která ukládá odkaz na rodiče. Dva způsoby implementace tohoto se zdají být...

  1. Použijte funkci init k procházení v okamžiku, kdy je vytvořen vnořený objekt, nebo...
  2. Předáte vnořený objekt funkci, která vyplní vlastnost rodiče

Oba přístupy mají stejný problém...

Jak udržujete rodiče, jak se vnořený objekt zvětšuje/mění??

Pokud přidám nový pod-pod-objekt, jak se vyplní jeho vlastnost rodiče? Pokud (1) používáte funkci init, inicializace je již dokončena, takže byste museli (2) předat objekt funkci, aby vyhledala nové děti a přidala odpovídající vlastnost rodiče.

Použití ES6 Proxy pro přidání parent, kdykoliv je objekt/podobjekt nastaven

Následující přístup spočívá ve vytvoření handleru pro proxy, který pokaždé při nastavení objektu přidá vlastnost parent. Tento handler jsem nazval parenter. Odpovědnosti parenter jsou rozpoznat, kdy je objekt nastaven, a pak...

  1. Vytvořte simulovaný proxy s odpovídajícím parent a handlerem parenter

    var p = new Proxy({parent: target}, parenter);
    
  2. Kopírujte do poskytnutých vlastností objektů-- Protože v tomto cyklu nastavujete vlastnosti proxy, handler parenter funguje rekurzivně; vnořené objekty mají rodiče na každé úrovni

    for(key in value){
        p[key] = value[key];
      }
    
  3. Nastavte proxy, nikoli dodaný objekt

    return target[prop] = p;
    

Celý kód

var parenter = {
  set: function(target, prop, value){
    if(typeof value === "object"){
      var p = new Proxy({parent: target}, parenter);
      for(key in value){
        p[key] = value[key];
      }
      return target[prop] = p;
    }else{
      target[prop] = value;
    }
  }
}

var root = new Proxy({}, parenter);

// some examples
root.child1 = {
    color: "red", 
    value: 10, 
    otherObj: { 
       otherColor: "blue", 
       otherValue: 20
    }
}

// parents exist/behave as expected
console.log(root.child1.color)                 // "red"
console.log(root.child1.otherObj.parent.color) // "red"

// new children automatically have correct parent
root.child2 = {color: "green", value3: 50};
console.log(root.child2.parent.child1.color)   // "red"

// changes are detected throughout
root.child1.color = "yellow"
console.log(root.child2.parent.child1.color)   // "yellow"

Všimněte si, že všechny kořenové děti mají vždy vlastnosti rodiče, i děti, které jsou přidány později.

Související články