Объекты Javascript: получить родительский объект

У меня есть следующий (вложенный) объект:

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

Следующее, что я делаю, это ссылаться на подобъект следующим образом:

var s = obj.subObj;

Теперь мне хотелось бы получить ссылку на объект obj вне переменной s. Что-то вроде:

var o = s.parent;

Как это возможно?

Ответ 1

Нет. Нет способа узнать, из какого объекта он произошел.

s и obj.subObj оба просто имеют ссылки на один и тот же объект.

Вы также можете сделать:

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

Теперь у вас есть три ссылки, obj.subObj, obj2.subObj и s, к одному и тому же объекту. Ни один из них не является особенным.

Ответ 2

Вложенный объект (дочерний элемент) внутри другого объекта (родительский) не может получать данные непосредственно от своего родителя.

Посмотрите на это:

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

Если вы зададите основному объекту, что его дочернее имя (main.child.name), вы получите его.
Вместо этого вы не можете сделать это наоборот, потому что ребенок не знает, кто его родитель.
(Вы можете получить main.name, но вы не получите main.child.parent.name).

Кстати, функция может быть полезна для решения этой проблемы.
Позвольте расширить код выше:

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

Внутри функции init вы можете получить родительский объект, просто называя this.
Поэтому мы определяем свойство parent непосредственно внутри объекта child.
Затем (необязательно) мы можем удалить метод init.
Наконец, мы возвращаем основной объект в качестве результата функции init.

Если вы попытаетесь получить main.child.parent.name, теперь вы получите это правильно.
Это немного сложно, но он отлично работает.

Ответ 3

Это старый вопрос, но когда я наткнулся на него, ища ответ, я подумал, что добавлю свой ответ на этот вопрос, чтобы помочь другим, как только у них возникнут те же проблемы.

У меня есть такая структура:

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

В настоящее время, ссылаясь на один из подучетов, я не знаю, как получить родительский node с ним значение имени "Основной уровень".

Теперь я представляю рекурсивную функцию, которая перемещает структуру и добавляет родительский атрибут к каждому объекту node и заполняет его своим родителем, как это.

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

Затем я просто вызываю эту функцию и теперь могу получить родительский элемент текущего node в этом дереве объектов.

setParent(structure.root);

Если теперь у меня есть ссылка на секцию sub node от root, я могу просто позвонить.

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

и он выведет "Основной уровень".

Надеюсь, что это поможет.

Ответ 4

Многие из ответов здесь включают в себя цикл через объект и "вручную" (хотя и программно) создание родительского свойства, которое хранит ссылку на родителя. Два способа реализации этого, похоже,...

  • Используйте функцию init для прокрутки во время создания вложенного объекта или...
  • Поместить вложенный объект в функцию, которая заполняет родительское свойство

Оба подхода имеют одинаковую проблему...

Как вы поддерживаете родителей по мере роста/изменения вложенного объекта?

Если я добавлю новый суб-объект, как он получит его родительское свойство? Если вы (1) используете функцию init, инициализация уже выполнена и завершена, вы должны (2) передать объект через функцию для поиска новых детей и добавить соответствующее родительское свойство.

Использование ES6 Proxy для добавления parent, когда объект/под-объект set

Приведенный ниже подход к созданию обработчика прокси всегда добавляет родительское свойство каждый раз, когда объект установлен. Я назвал обработчик обработчиком parenter. Обязанности parenter должны распознавать, когда объект установлен, а затем...

  • Создайте фиктивный прокси с соответствующим обработчиком parent и parenter

    var p = new Proxy({parent: target}, parenter);
    
  • Копирование в свойствах поставляемых объектов - . Поскольку вы устанавливаете свойства прокси в этом цикле, обработчик parenter работает рекурсивно; вложенные объекты предоставляются родителям на каждом уровне

    for(key in value){
        p[key] = value[key];
      }
    
  • Установите прокси-сервер, а не поставляемый объект

    return target[prop] = p;
    

Полный код

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"

Обратите внимание, что все корневые дети всегда имеют родительские свойства, даже дочерние элементы, которые добавляются позже.

Ответ 5

Для этого существует более "гладкое" решение:)

var Foo = function(){
  this.par = 3;

  this.sub = new(function(t){ //using virtual function to create sub object and pass parent object via 't'
    this.p = t;
    this.subFunction = function(){
      alert(this.p.par);
    }
  })(this);
}

var myObj = new Foo();
myObj.sub.subFunction() // will popup 3;

myObj.par = 5;
myObj.sub.subFunction() // will popup 5;

Ответ 6

Чтобы продолжить повторение ответа Mik, вы также можете рекурсивно прикрепить родителя ко всем вложенным объектам.

var myApp = {

    init: function() {
        for (var i in this) {
            if (typeof this[i] == 'object') {
                    this[i].init = this.init;
                    this[i].init();
                    this[i].parent = this;
            }
        }
        return this;
    },

    obj1: {
        obj2: {
            notify: function() {
                console.log(this.parent.parent.obj3.msg);
            }
        }
    },

    obj3: {
        msg: 'Hello'
    }

}.init();

myApp.obj1.obj2.notify();

http://jsbin.com/zupepelaciya/1/watch?js,console

Ответ 7

Попробуйте это, пока не появится ответ "нет":

function parent() {
  this.child;
  interestingProperty = "5";
  ...
}

function child() {
  this.parent;
  ...
}

a = new parent();
a.child = new child();
a.child.parent = a; // this gives the child a reference to its parent

alert(a.interestingProperty+" === "+a.child.parent.interestingProperty);

Ответ 8

Вы можете попробовать это (это использует конструктор, но я уверен, что вы можете немного изменить его):

function Obj() {
    this.subObj = {
        // code
    }
    this.subObj.parent = this;
}

Ответ 9

Я работал над решением для поиска родительского объекта текущего объекта для моего собственного проекта для домашних животных. Добавление ссылки на родительский объект в текущем объекте создает циклическое соотношение между этими двумя объектами.

Рассмотрим -

var obj = {
    innerObj: {},
    setParent: function(){
        this.innerObj.parent = this;
    }
};
obj.setParent();

Теперь переменная obj будет выглядеть следующим образом:

obj.innerObj.parent.innerObj.parent.innerObj...

Это не хорошо. Единственным решением, которое я нашел до сих пор, является создание функции, которая выполняет итерацию по всем свойствам внешнего объекта до тех пор, пока не будет найдено совпадение для текущего объекта, а затем возвращается этот объект.

Пример -

var obj = {
    innerObj: {
        innerInnerObj: {}
    }
};

var o = obj.innerObj.innerInnerObj,
    found = false;

var getParent = function (currObj, parObj) {
    for(var x in parObj){
        if(parObj.hasOwnProperty(x)){
            if(parObj[x] === currObj){
                found = parObj;
            }else if(typeof parObj[x] === 'object'){
                getParent(currObj, parObj[x]);
            }
        }
    }
    return found;
};

var res = getParent(o, obj); // res = obj.innerObj

Конечно, не зная или не ссылаясь на внешний объект, нет никакого способа сделать это. Это не практично и не является эффективным решением. Я продолжу работу над этим и, надеюсь, найду хороший ответ на эту проблему.

Ответ 10

Вам понадобится ребенок, чтобы сохранить родительскую переменную. Поскольку родитель является единственным объектом, который имеет к нему доступ эту переменную, ему также понадобится функция, которая помещает эту переменную в дочерний элемент этой переменной, что-то вроде этого.

var Parent = {
  Child : {
    that : {},
  },
  init : function(){
    this.Child.that = this;
  }
}

Чтобы проверить это, попробуйте запустить это в Firefox Scratchpad, это сработало для меня.

var Parent = {
  data : "Parent Data",

  Child : {
    that : {},
    data : "Child Data",
    display : function(){
      console.log(this.data);
      console.log(this.that.data);
    }
  },
  init : function(){
    this.Child.that = this;
  }
}

Parent.init();
Parent.Child.display();

Ответ 11

Просто сохраняя родительское значение в дочернем атрибуте

var Foo = function(){
    this.val= 4;
    this.test={};
    this.test.val=6;
    this.test.par=this;
}

var myObj = new Foo();
alert(myObj.val);
alert(myObj.test.val);
alert(myObj.test.par.val);

Ответ 12

когда я загружаю объект json, я обычно устанавливаю отношения путем итерации через массивы объектов следующим образом:

    for (var i = 0; i < some.json.objectarray.length; i++) {
        var p = some.json.objectarray[i];
        for (var j = 0; j < p.somechildarray.length; j++) {
            p.somechildarray[j].parent = p;
        }
    }

тогда вы можете получить доступ к родительскому объекту какого-либо объекта в somechildarray с помощью .parent