JavaScript отражает изменения свойств во всех ссылках на объекты

#javascript #reference

#javascript #ссылка

Вопрос:

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

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

скрипка js

     var OO = function(o, parent){
        this.parent = parent || null;
        this.init(o);
        return this;
    };

    OO.prototype = {
        init: function(o){
            this.obj = typeof o === 'object' ? new OO(o.name, this) : o;
            this.type = typeof o === 'object' ? 'object' : 'string';

            if( typeof o === 'string' ){
                this.change();
                console.log(this.parent); // Here top-level oo object holds values called in change() function. I want the variable ( oo_var ) holding this top-level oo to have same property values too.
                this.add();
            }               
        },

        change: function(){
            this.parent.obj = 'Orange'; // Holds {} before changing
            this.parent.type = 'string'; // 'object' before changing
        },

        add: function(){
            this.parent.another_obj = 'Another';
            this.parent.another_type = 'another string';
        }
    };

    var oo_var = new OO({name: 'Apple'}); // This var doesn't refresh the obj amp; type property values applied in change() function. But has properties added in add() function.
  

У меня много уровней вложенных объектов с братьями и сестрами на каждом уровне.

Комментарии:

1. Ваш init метод выполняет запись в oo_var.obj и .type после создания дочернего объекта — и после того, как он .change() их разделяет.

2. Чего вы действительно хотите? И почему создание объекта должно изменить его родительский элемент?

3. @Bergi, я меняю родительские свойства с дочерних. Когда я смотрю после их изменения (консоль. войдите в change() ), это выглядит нормально. Но когда я смотрю извне (консоль. log после var oo_var = …) родительский элемент по-прежнему имеет начальные значения. См. jsfiddle

4. Я хочу иметь возможность изменять значения свойств родительских / дедушкиных свойств у дочерних элементов и получать к ним доступ oo_var .

5. Вы уже можете получить доступ к родительским элементам и изменить их из дочерних элементов. Ваша проблема в том, что ваша родительская инициализация происходит после инициализации вашего дочернего элемента, поэтому «измененные» значения будут перезаписаны «начальными» значениями. Ваш init метод не должен вызывать change or add . Зачем это нужно?

Ответ №1:

Конструктор должен выполнять только создание, а не изменять состояние чего-либо. Ему не нужно вызывать init метод, и он определенно не должен вызывать (даже косвенно) change метод.

Сделайте это

 function OO(o, parent) {
    this.parent = parent || null;
    this.type = typeof o;
    this.obj = this.type === 'object' ? new OO(o.name, this) : o;
}
OO.prototype.change = function() {
    this.parent.obj = 'Orange'; // Holds {} before changing
    this.parent.type = 'string'; // 'object' before changing
};
OO.prototype.add = function(){
    this.parent.another_obj = 'Another';
    this.parent.another_type = 'another string';
};

var oo_var = new OO({name: 'Apple'});
console.dir(oo_var);
oo_var.obj.change();
oo_var.obj.add();
console.dir(oo_var);
  

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

Если вы не хотите вызывать методы самостоятельно, вы можете использовать для этого метод:

 OO.prototype.init = function() {
    if (this.type === 'object' ) {
        this.obj.init();
    } else if (this.type === 'string') {
        this.change();
        this.add();
    }
};

var oo_var = new OO({name: 'Apple'});
console.dir(oo_var);
oo_var.init();
console.dir(oo_var);