Javascript-objekter: hent forelder


Jeg har følgende (nestede) objekt:

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

Neste ting jeg gjør er å referere til underobjektet på denne måten:

var s = obj.subObj;

Nå ønsker jeg å få en referanse til objektet obj fra variabelen s. Noe sånt som:

var o = s.parent;

Er dette på en eller annen måte mulig?

Svar #1

Et nestet objekt (barn) inne i et annet objekt (foreldre) kan ikke hente data direkte fra sin forelder.

Ta en titt på dette:

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

Hvis du spør hovedobjektet hva barnet heter (main.child.name) vil du få det.
Derimot kan du ikke gjøre det omvendt fordi barnet ikke vet hvem forelderen er.
(Du kan få main.name men du vil ikke få main.child.parent.name).

Forresten, en funksjon kan være nyttig for å løse dette hintet.
La oss utvide koden ovenfor:

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

Inne i init-funksjonen kan du få foreldreaktobjektet enkelt ved å kalle this.
Så vi definerer parent-egenskapen direkte inne i child-objektet.
Deretter (valgfritt) kan vi fjerne init-metoden.
Til slutt gir vi tilbake hovedobjektet som output fra init-funksjonen.

Hvis du prøver å hente main.child.parent.name nå, vil du få det riktig.
Det er litt vanskelig, men det fungerer fint.

Svar #2

Nei. Det er ingen måte å vite hvilket objekt det kom fra.

s og obj.subObj har begge bare referanser til det samme objektet.

Du kunne også gjøre:

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

Du har nå tre referanser, obj.subObj, obj2.subObj og s, til samme objekt. Ingen av dem er spesielle.

Svar #3

Dette er et gammelt spørsmål, men da jeg kom over det mens jeg lette etter et svar, tenkte jeg at jeg ville legge til mitt svar på dette for å hjelpe andre så snart de fikk det samme problemet.

Jeg har en struktur som dette:

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

For øyeblikket, ved å referere til en av undernodene, vet jeg ikke hvordan jeg får foreldrenoden med dens navneverdi "Main Level".

Nå introduserer jeg en rekursiv funksjon som går gjennom strukturen og legger til et forelder-attributt til hvert nodeobjekt og fyller det med dets forelder slik.

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

Da kaller jeg bare den funksjonen og kan nå få forelderen til den nåværende noden i dette objekt-treet.

setParent(structure.root);

Hvis jeg nå har en referanse til sekund-subnoden til root, kan jeg bare kalle.

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

og det vil vise «Hovednivå».

Håper dette hjelper..

Svar #4

Mange av svarene her innebærer å gå gjennom et objekt og "manuelt" (selv om det er programmessig) opprette en overordnet egenskap som lagrer referansen til overordnet. De to måtene å implementere dette på ser ut til å være...

  1. Bruk en init-funksjon for å gå gjennom når det nestede objektet opprettes, eller...
  2. Lever det nestede objektet til en funksjon som fyller ut overordnet egenskap

Begge tilnærmingene har det samme problemet...

Hvordan opprettholder man foreldre etter hvert som det nestede objektet vokser/endres??

Hvis jeg legger til et nytt under-under-objekt, hvordan får det fylt ut sin foreldreegenskap? Hvis du (1) bruker en init-funksjon, er initialiseringen allerede gjort og over, så du må (2) sende objektet gjennom en funksjon for å søke etter nye barn og legge til riktig foreldreegenskap.

Bruke ES6 Proxy for å legge til parent når et objekt/underdelobjekt blir set

Fremgangsmåten nedenfor er å lage en håndterer for en proxy som alltid legger til en parent-egenskap hver gang et objekt settes. Jeg har kalt denne håndtereren for parenter-håndtereren. Parenter-ansvaret er å gjenkjenne når et objekt blir satt og deretter å...

  1. Opprett en dummy-proxy med den passende parent og parenter-behandleren

    var p = new Proxy({parent: target}, parenter);
    
  2. Kopier inn de leverte objektets egenskaper-- Fordi du setter proxy-egenskapene i denne løkken fungerer parenter-behandleren rekursivt; nestede objekter får foreldre på hvert nivå

    for(key in value){
        p[key] = value[key];
      }
    
  3. Sett proxien, ikke det leverte objektet

    return target[prop] = p;
    

Full kode

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"

Merk at alle rotbarn alltid har foreldreegenskaper, selv barn som legges til senere.

Relaterte artikler