Реагирует на изменение переменной, но не должно

#javascript #json #reactjs #react-hooks

#javascript #json #reactjs #реагирует-хуки

Вопрос:

У меня проблема примерно на 3 часа, и я не понимаю, почему,

Приведенный ниже код должен объяснить мою проблему:

 import {useEffect} from 'react'

function shuffle(tab) {
  console.table(tab) //shows initialdata
  var i, j, tmp;
  for (i = tab.length - 1; i > 0; i--) {
      j = Math.floor(Math.random() * (i   1));
      tmp = tab[i];
      tab[i] = tab[j];
      tab[j] = tmp;
  }
  return tab;
}

function App() {

  useEffect(() => {
    const initaldata = [{a:1}, {a:2}, {a:3}, {a:5}]
    console.table(initaldata) //shows initialdata
    const finaldata = initaldata 
    console.table(shuffle(finaldata)) //shows initialdata shuffled
    console.table(initaldata) //shows initialdata shuffled,  why ?

  }, [])
  return null;
}
 

Я пробовал множественные решения, такие как изолированный «shuffle (initialdata)» в функции.

Тот факт, что функция shuffle обновляет все мои переменные, делает весь мой код плохим.

Спасибо, и я надеюсь, что вы найдете решение. (и извините, если есть какие-то ошибки, я французский)

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

1. shuffle изменяет исходный массив.

2. вызывается refrence, глубокое клонирование аргументов в функции shuffle, tab = tab.slice()

Ответ №1:

JavaScript передает им объекты по ссылке, вот почему. Если вы хотите избежать этого, измените цикл for с помощью map

 ....
const toReturn = tab.map(item =>{
...
});

return toReturn
 

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

1. Это не очень помогает, потому что алгоритм перемешивания изменится. Фишер-Йейтс должен делать это на месте.

Ответ №2:

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

 const finaldata = initaldata 
 

оба finaldata и initaldata по-прежнему указывают на один и тот же массив в памяти. Если вы не хотите изменять свои исходные данные, вам нужно будет мелко или глубоко скопировать ваш массив перед его изменением.

Ответ №3:

Вы могли бы попытаться скопировать массив таким образом, прежде чем запускать shuffle =>

 const finalData = JSON.parse(JSON.stringify(initialData));
console.table(initialData);
 

Надеюсь, это может помочь
https://dev.to/samanthaming/how-to-deep-clone-an-array-in-javascript-3cig

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

1. Это неэффективно. Однако для этого не нужно глубокого клонирования array.slice() .