цикл forEach не обновляет значение объекта - PullRequest
2 голосов
/ 23 мая 2019

Я пытаюсь сделать один цикл и обновить свойство объекта каждым значением цикла, но происходит нечто неожиданное:

Первый console.log печатает свойство объекта day, обновленное, как и ожидалось.Второй, однако, который печатает полный объект, показывает свойство day со значением final forEach.

Пример: data.days = [ 5, 6 ]

Печать первого цикла:

newData.date: 5
{prop1: x, prop2: x...., date: 6}

Печать второго цикла:

newData.date: 6
{prop1: x, prop2: x...., date: 6}

Это мой код:

data.days.forEach(day => {
    let newData;
    newData = data.data;
    newData.date = day;
    console.log('newData.date: ' + newData.date)
    console.log(newData)
})

Я пытался создатьnewData переменная из forEach или for цикла вместо этого, но у меня тот же результат.

Ответы [ 4 ]

1 голос
/ 23 мая 2019

Ваша проблема здесь:

...
let newData;
newData = data.data;
...

Вы не создаете новый объект с переменной newData, вместо этого вы просто ссылаетесь на один и тот же объект data.data в каждой итерации. Вот почему окончательное значение newData всегда будет тем, что установлено на последней итерации цикла.

Если вы хотите новый отдельный объект для каждого цикла, вам нужно (глубоко) клонировать / скопировать data.data вместо того, чтобы просто ссылаться на него:

var data = {};
data.data = { prop1: 'x', prop2: 'x' };
data.days = [ 5, 6 ];

data.days.forEach(day => {
    let newData;
    newData = Object.assign({}, data.data); 
    newData.date = day;
    console.log('newData.date: ' + newData.date)
    console.log(newData)
});

Примечание: Object.assign делает мелкую копию объекта, вам нужно прибегнуть к чему-то другому, если нужно глубоко копировать объект.

1 голос
/ 23 мая 2019

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

Вы можете увидеть это здесь:

enter image description here

Строка просто регистрируется как статическая строка, но объект обрабатывается специально, с подсветкой синтаксиса и расширением представлений свойств и тому подобным.

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

let days = [5, 6];
let newData = {};

days.forEach(day => {
    newData.date = day;
    console.log('newData.date: ' + newData.date);
    console.log(JSON.stringify(newData));
    console.log(newData);
});

Это дает:

enter image description here

0 голосов
/ 23 мая 2019

Согласно документации ECMAScript, ссылка

в 22.1.3.12 Array.prototype.forEach (callbackfn [, thisArg])

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

0 голосов
/ 23 мая 2019

У объектов нет метода forEach (это в основном для массивов), но вы можете перебирать их свойства с помощью for (let prop in object).

В вашем примере:

for (let day in data.days) {
    // Do your stuff
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...