JavaScript передает аргумент в функцию, сохраняя данные аргумента без изменений - PullRequest
1 голос
/ 27 июня 2019

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

function objBuild() {

    var obj_old = {}; // original object
    var obj_new = {}; // updated object

    // set values for original object
    obj_old.val01 = "val01_old";
    obj_old.val02 = "val02_old";
    obj_old.val03 = "val03_old";

    // set values for new object using
    // the original object as a template
    obj_new = objUpdate(obj_old);

    console.log(obj_old); // this shows obj_new data which I don't want
    console.log(obj_new); // this shows obj_new data which I want

}

function objUpdate(obj) {

    obj.val03 = "val03_new";

    return obj;

}

Я ожидал, что новый объект будет обновлен с новым значением, которым оно является, однако старый объект также обновляется.

Может быть, функция берет старый объект в качестве ссылки, и хотя я возвращаю отдельное значение, он вспоминает, что с ним случилось?

Я не уверен, но если это так, то возможно ли сохранить старый Объект в целости?

Ответы [ 3 ]

1 голос
/ 27 июня 2019

Помните, что объекты, включая массивы, передаются по ссылке, а строки, логические значения и числа передаются по значению.

Здесь вы передаете объект (по ссылке), поэтому он изменяет значения старого объекта.И старые, и новые объекты указывают на одно и то же значение.

function objBuild() {

    var obj_old = {}; // original object
    var obj_new = {}; // updated object

    // set values for original object
    obj_old.val01 = "val01_old";
    obj_old.val02 = "val02_old";
    obj_old.val03 = "val03_old";

    // set values for new object using
    // the original object as a template
    obj_new = objUpdate(obj_old);

    console.log(obj_old); // this shows obj_new data which I don't want
    console.log(obj_new); // this shows obj_new data which I want

}

function objUpdate(obj_old) {
    var obj = JSON.parse(JSON.stringify(obj_old));
    obj.val03 = "val03_new";

    return obj;
}

objBuild();
1 голос
/ 27 июня 2019

Пожалуйста, прочитайте: Является ли JavaScript языком передачи по ссылке или передачей по значению?

В javascript объекты «технически» передаются «ссылкой».Следовательно, исходное значение изменяется, поскольку obj фактически является исходным объектом.

Вам необходимо клонировать объект, и существует обширный сценарий о том, «как» вы должны это сделать, посколькуобъект может быть скопирован или скопирован.Подробнее об этом читайте здесь: Какой самый эффективный способ глубокого клонирования объекта в JavaScript? и здесь: Как правильно клонировать объект JavaScript?

В любом случае, чтобы решить вашу проблему, просто используйте Object.assign для нового объекта, чтобы скопировать значения исходного объекта, для вашего случая этого достаточно, несмотря на то, что я рекомендую вам прочитать вышеупомянутые посты, чтобы узнать, когда и как правильнокопировать объекты.

function objBuild() {

    var obj_old = {}; // original object
    var obj_new = {}; // updated object

    // set values for original object
    obj_old.val01 = "val01_old";
    obj_old.val02 = "val02_old";
    obj_old.val03 = "val03_old";

    // set values for new object using
    // the original object as a template
    obj_new = objUpdate(obj_old);

    console.log(obj_old); // this shows obj_new data which I don't want
    console.log(obj_new); // this shows obj_new data which I want

}

function objUpdate(obj) {
    var _cloned = Object.assign({}, obj);
    _cloned.val03 = "val03_new";

    return _cloned;

}

objBuild();
1 голос
/ 27 июня 2019

Вы на самом деле не создаете новый объект, вы устанавливаете старый объект на новый объект. Итак, вы правы, на старое значение объекта все еще ссылаются.

Если вы хотите создать новый объект, и у вас нет вложенных объектов, я бы использовал Object.assign(). Это делает поверхностную копию объекта. Вы могли бы сделать что-то вроде этого:

obj_new = objUpdate(Object.assign({}, obj_old));

Это создаст новый объект с перечисляемыми свойствами старого объекта.

Если у вас есть вложенные объекты, они все равно будут скопированы по ссылке, поэтому я бы перебрал объект и скопировал свойства таким образом.

...