skip to Main Content

I’m trying to make sense of the second code but my mind only wraps around the first code which is mine (it’s already obvious since it’s awful). I understand the ternary operator (and even the second code) but my mind only wants to accept the first code as the better code although it’s long and awful (but to me it’s more comprehensive); it this a normal behavior at the beginning of my learning?
by the way it’s been only three days since i started learning JS so feel free to add any advice that might help a stupid like me to improve.

my code:

<button onclick="
    playGame('tails');
  ">tails</button>

  <button onclick="
    playGame('heads')
  ">heads</button>

  <script>
    let result = '';

    let score = {
      wins: 0,
      losses: 0
    }

    let scoresFromLocalStorage = localStorage.getItem('scores');
    if (scoresFromLocalStorage) {
      score = JSON.parse(scoresFromLocalStorage);
    } 

    function playGame(choice) {
      const randomNumber = Math.random();
      
      if (randomNumber < 0.5) {
        result = 'heads';
      } else {
        result = 'tails';
      } 

      console.log('Computer: ' + result);
      console.log('You: ' + choice);

      if (choice === result) {
        console.log('You win');
        score.wins += 1;
      } else {
        console.log('You lost');
        score.losses += 1;
      } 

      

      let jsonScore = JSON.stringify(score);
      localStorage.setItem('scores', jsonScore);
        
      score = JSON.parse(localStorage.getItem('scores'));
      console.log(score);
    }
  
  </script> 

second or the better code:

<button onclick="
      playGame('heads');
    ">heads</button>

    <button onclick="
      playGame('tails');
    ">tails</button>

    <script>
      // We can use const here since score is a reference
      // so we can modify it even if it uses const.
      const score = JSON.parse(localStorage.getItem('score')) || {
        wins: 0,
        losses: 0
      };

      function playGame(guess) {
        const randomNumber = Math.random();
        const result = randomNumber < 0.5 ? 'heads' : 'tails';

        console.log(guess === result ? 'You win!' : 'You lose!');

        if (guess === result) {
          score.wins++;
        } else {
          score.losses++;
        }
        console.log(score);

        localStorage.setItem('score', JSON.stringify(score));
      }
    </script>

Saving the results in localStorage, which in both codes is a success. but i really can’t wrap my head around using the second code.

2

Answers


  1. In my case, I used to use long code instead of short effcient code.
    But as time goes by, I wanted to make my code shorter. So I changed my code style like second one. I think your behavior(prefer long codes) is general behaviors among beginer of programers. (Even professional programers)

    By the way. I’d like to suggest you some improvement.
    ‘++’ and ‘–‘ operators are not used very well these days.
    You can use ‘+=’ operators as you did. (score.wins += 1).
    And this is my subjective suggestion.
    In second code,

    console.log(guess === result ? 'You win!' : 'You lose!');
    
    if (guess === result) {
      score.wins++;
    } else {
      score.losses++;
    
    }
    

    your code is better than this code.
    because your code is more intuitive than second code.
    I prefer seperate codes by same categories of their roles.

    You don’t need to apply my suggestion because I’m not a professional programer and even I’m not good at English…. Sry for my grammar errors and a contextual flaw.

    Login or Signup to reply.
  2. I’m not sure what you mean by "how can I compare and analyze two scripts", but I will do it myself below and you can follow along.

    As to "normal behavior", I’m sure it’s pretty common to feel like this.

    (I feel the core question is rather opinion based, but the individual concepts are useful.)

    Comparison

    As is, I prefer the other code.

    It’s quite hard to compare code side-by-side in Markdown, especially as the structure is different, so I’ll try go through the logical sections. Here goes…

    I’ve used only the script, as the HTML is the same.
    I’ve normalized the 'scores' and 'score' names and keys to 'scores'.

    Getting the scores from storage or using a default

    Your code:

    let scores = {
      wins: 0,
      losses: 0
    }
    
    let scoresFromLocalStorage = localStorage.getItem('scores');
    if (scoresFromLocalStorage) {
      scores = JSON.parse(scoresFromLocalStorage);
    } 
    

    Other code:

    const scores = JSON.parse(localStorage.getItem('scores')) || {
      wins: 0,
      losses: 0
    };
    

    Your code creates a mutable variable set to the default value. It then reads the data from localStorage and stores it in a variable. If the variable is not falsy (i.e., the item exists in storage and is not an empty string), the value is parsed as JSON and assigned to the scores variable.

    The other code reads the data from localStorage and parses it. Assuming the data is valid if present, this will either return a scores object or null. It then uses a logical or (||) to choose between this and the default: if it is falsy, the default is used. (I would use ??, the nullish coalescing operator ??; it’s designed specifically for this kind of use case.)

    Ignoring the differences in behavior when the stored data is not what is expected, these two pieces of code are identical in outcome, aside from the difference between let and const.

    Here’s an intermediate refactoring of your code:

    let scoresFromLocalStorage = JSON.parse(localStorage.getItem('scores'));
    const scores = scoresFromLocalStorage
      ? scoresFromLocalStorage
      : {
          wins: 0,
          losses: 0
        };
    

    The next step is replacing the temp variable and ternary with a logical or operator or nullish coalescing operator, as in the other code.

    playGame function

    I have renamed your choice variable to guess for ease of comparison.

    Your code has this extra bit that the other code does not:

    console.log('Computer: ' + result);
    console.log('You: ' + guess);
    

    I have left it out for the comparisons.

    Getting a random number

    You both do:

    const randomNumber = Math.random();
    

    Determining the result

    Your code:

    // Top-level
    
    let result = '';
    
    // In function
    
    if (randomNumber < 0.5) {
      result = 'heads';
    } else {
      result = 'tails';
    }
    

    Other code:

    const result = randomNumber < 0.5 ? 'heads' : 'tails';
    

    The main difference here is that you use an if and the other code uses a ternary. as a consequence, your code needs the variable declared earlier, so that it can be reassigned.
    For some reason, you use a global variable instead of a function-local variable; you can instead declare the variable inside the function instead of at the top level scope.

    Determining if the guess was correct

    I have changed the other code’s ++ to += 1 for the sake of comparison.
    And the log messages.

    Your code:

    if (guess === result) {
      console.log('You win!');
      scores.wins += 1;
    } else {
      console.log('You lose!');
      scores.losses += 1;
    }
    

    The other code:

    console.log(guess === result ? 'You win!' : 'You lose!');
    
    if (guess === result) {
      scores.wins += 1;
    } else {
      scores.losses += 1;
    }
    

    The only difference here is that the other code opts to do the comparison twice to allow the use of a single log statement, instead of doing the comparison once and having the extra line.
    In real code, the choice should be made based on the context.

    Alternative code:

    console.log(guess === result ? 'You win!' : 'You lose!');
    
    scores[guess === result ? 'wins' : 'losses'] += 1;
    

    Don’t use this for this simple case. In more complex situations, though, variations of this actually can be really useful, especially when there are lots of abstractions. E.g., when using a map to determine the key, instead of an equality check.

    Logging and storing the result

    Your code:

    let jsonScores = JSON.stringify(scores);             // Stringify
    localStorage.setItem('scores', jsonScores);          // Store
    scores = JSON.parse(localStorage.getItem('scores')); // Load, parse and assign
    
    console.log(scores);                                 // Log
    

    Other code:

    console.log(scores); // Log
    
    localStorage.setItem('scores', JSON.stringify(scores)); // Stringify and store
    

    Okay, you lost me here. You stringify the scores object, store it, load it from storage, parse it, and assign it to the scores variable. Why? The storing does not affect the scores object. The only difference this would ever make would be if there were values in the object that could not be stringified, in which case this is not the way to go about and your code is broken. There is no need for this pointless cycle; removing the "load, parse, assign" bit and refactoring to remove the temporary variable gives you the other code:

    Remove:

    let jsonScores = JSON.stringify(scores);              // Stringify
    localStorage.setItem('scores', jsonScores);          // Store
    
    console.log(scores);                                 // Log
    

    Refactor (optional):

    localStorage.setItem('scores', JSON.stringify(scores)); // Stringify and store
    
    console.log(scores); // Log
    

    Reorder the statements if wanted/needed.

    Notes

    The other code uses approaches that reduce the use of temporary variables. This is very useful in TypeScript, especially in the case of ones that would have to either have an arbitrary default that is never used, or have undefined included in the type (which is a pain). For example, the two methods of determining the result based on the random number.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search