Search code examples
javascriptobjectshort-circuiting

using Short-Circuiting ( || ) in Object in JavaScript


this block of code takes the values of the scored property and puts them in duplication object as a key and how many times the name got duplicated as a value using the || operator. I understand that the || operator will return the first truthy value or the last value if all of the values are falsy, however, I didn't understand duplication[x]++ what does the ++ sign do exactly? and why we put the (duplication[x]=1) between parentheses

const game = {
  score: "4:0",
  scored: ["Lewandowski", "Gnarby", "Lewandowski", "Hummels"],
}; 


const duplication = {};
for (let x of game.scored) {
 duplication[x]++ || (duplication[x]=1) // I'm confused in this line
}
 
console.log(duplication);

Solution

  • The non-descriptive variable names don't really help to explain the situation. Let's start of by rewriting the code with more descriptive variable names.

    const game = {
      score: "4:0",
      scored: ["Lewandowski", "Gnarby", "Lewandowski", "Hummels"],
    }; 
    
    
    const goals = {};
    for (const player of game.scored) {
      goals[player]++ || (goals[player] = 1);
    }
     
    console.log(goals);
    

    goals[player]++ increments the goals for player by 1 and returns the old value. The tricky thing in goals[player]++ is that player might not be present in goals yet. In which case undefined is returned (which is falsy). Because the value is falsy the second operand of the OR operator will be executed. (goals[player] = 1) will set the goals for player to 1.

    The code is essentially counting how often a specific name is present in the game.scored array. The presence of a name symbolises a goal made by them.

    A less cryptic way of writing similar code would be:

    const goals = {};
    for (const player of game.scored) {
      if (player in goals) {
        goals[player] += 1; // add 1 to the current score
      } else {
        goals[player] = 1; // no score present so use 1
      }
    }
    

    However I usually prefer to set a default value, this way you don't have to split the logic into two actions:

    const goals = {};
    for (const player of game.scored) {
      goals[player] ||= 0; // assign 0 if the current value is falsy
      goals[player] += 1;  // add 1 to the current value
    }
    

    Note that ||= is fairly new, if you write JavaScript for older browser you can use the following instead:

    if (!goals[player]) goals[player] = 0;