0

I'm working on a helper function within a bigger function.

I have an array of team object (each team looks like this {team:unique number of the team, points:0, goalDiff:0, goalsFor:0}) as the first argument of my function and I have an array of game results as a second argument (each game looks like this [number ref home team, number ref away team, goals scored by home team, goals scored by away team]).

My function looks at each game in the second array and allocate 2 points to the winning team and zero to the losing one. in case of draw, it allocates 1 point to each team. Function also counts the goals scored by each team.

    let computeGames = (arr, games) => {

  
    games.forEach((game) => {
      
      let homeTeamIndex = arr.findIndex(team => team.team === game[0])
      let awayTeamIndex = arr.findIndex(team => team.team === game[1])
      let homeTeam = arr[homeTeamIndex]
      let awayTeam = arr[awayTeamIndex]
    
      
      game[2] > game[3]
        ? (homeTeam.points += 2)
        : game[2] === game[3]
        ? ((homeTeam.points += 1), (awayTeam.points += 1))
        : (awayTeam.points += 2);
      homeTeam.goalsFor += game[2];
      awayTeam.goalsFor += game[3];
      homeTeam.goalDiff += game[2] - game[3];
      awayTeam.goalDiff += game[3] - game[2];
    });

  return arr
    
  };

My code is counting the points and goals as expected, but my issue is that when I execute something like the code below, the points are being counted in my teams array as well as in my doNotMutate array. I do not understand why teams is being mutated given it's a copy of teams that is passed to the function, not the teams array itself. If someone could explain, I'm getting really confused here.

Cheers

const teams = createTeams(number) // this is a helper function to generate my teams with all values = 0
let doNotMutate = [...teams]

doNotMutate= computeGames(doNotMutate,games)
  
  console.log(teams, doNotMutate)
5
  • Please give input and expected output Commented Nov 16, 2020 at 7:28
  • Doing [...teams] does not copy the objects stored within the array. You'll want to step through the array and map each item to {...obj} (i.e. [...teams].map(g=>({...g}))) or explore deep-clone implementations. Commented Nov 16, 2020 at 7:28
  • Objects are always "passed by reference", so although you're using the spread operator to perform a shallow copy, modifications done to the object properties will be reflected in both the original and the copied list. Commented Nov 16, 2020 at 7:31
  • Thanks James, I'll try that. So at the moment what's in my array is still a reference to the original object ? no matter in which array they are located ? Commented Nov 16, 2020 at 7:32
  • Yes. You can either deep-clone the objects or write your function so it doesn't mutate the list. I would recommend the latter. Commented Nov 16, 2020 at 7:38

1 Answer 1

2

Doing [...teams] does not copy the objects stored within the array. Each item of the array is simply copied into a new array. In your case each item is an object, meaning the new array will contain the exact same objects (think of them as "references to the same value" if that helps).

You can observe this:

teams[0] === doNotMutate[0] // true! (we don't want this)

You'll want to step through the array and map each item to a copy of itself ({...obj}). Something like this:

const doNotMutate = [...teams].map(game => ({...game}));

Alternatively, explore deep-clone implementations such as lodash's.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.