Need A Lot of Assistance From An Actual js Dev

I am new to programming.

I started reading Eloquent Javascript 3rd Edition, as the book comes highly recommended as a good place for beginners to start. Like every book that makes this claim, it seems to not be the case.

I already ran into problems in Chapter 2.

This is the same problem I run into in every language I’ve tried to use in my attempt to learn how to program.

I never quite understand how to properly construct loops. And it seems every dev making a book to help “beginners” always leaves out important details and assumes that the beginner isn’t a beginner, which is understandable, they are developers not teachers and Pedagogy is it’s own field, still, because of the lack of understanding I am stuck.

They explain the concept of a loop just fine, what it does, and why I’d use one but, they always fail to properly explain how to properly create one and the pieces it uses to do what it does, and how those pieces work with whatever interpreter, etc.

Moving on to where I am stuck…

Chapter 2 - Exercise 2 - FizzBuzz
Write a program that uses console.log to print all the numbers from 1 to 100,
with two exceptions. For numbers divisible by 3, print “Fizz” instead of the
number, and for numbers divisible by 5 (and not 3), print “Buzz” instead.
When you have that working, modify your program to print “FizzBuzz”
for numbers that are divisible by both 3 and 5 (and still print “Fizz” or
“Buzz” for numbers divisible by only one of those).

This was my solution for the Chapter 2 - Exercise 2 problem…


/*
for ( let indexCounter = 1; indexCounter <=100; indexCounter++){
  if ( indexCounter % 3 == 0)
    console.log("Fizz");
  else if ( indexCounter % 5 == 0)
    console.log("Buzz");
  else if ( indexCounter % 3 == 0 && indexCounter % 5 == 0)
    console.log("FizzBuzz");
    else ( indexCounter == Number )
  console.log(indexCounter);
}
*/

It works… Kind of… It generates output but, it’s not the correct output after I compared my solution to the author’s. There is a semantic error and I can’t understand why. I am bashing my head against the wall feeling like a total failure in life, and I am, wanting to jump off my roof, and end my existence for being such a failure. For those who might be concerned with my statement, don’t worry, I won’t but, I feel like it.

The author’s solution is here…

/*
for (let n = 1; n <= 100; n++) {
  let output = "";
  if (n % 3 == 0) output += "Fizz";
  if (n % 5 == 0) output += "Buzz";
  console.log(output || n);
}
*/

When I look at the author’s solution… I just can’t understand what it’s doing or even how it’s doing it. I’ve re-read the chapter 3 times now and it’s just not clicking. The way the author explains it does not stick or make sense to me. I am extremely bad with memorization and it seems the author wants me to memorize a ton of stuff.

I understand the for loop and understand that for loops are great for iteration on a set of values and that if I run into a scenario like this I should use a for loop rather than a while loop. In this case the range of 1-100 are the numbers I am iterating over.

for (let n = 1; n <= 100; n++)

One other thing that throws me off is…
Why define the variable inside the for loop? Why not before?
Is this done because of scope? Aka Local variable being safer than a global? Am I even understanding that?
The author uses “let n = 1” which I am assuming acts as an index counter but, I am not sure.
Another thing is how does the JavaScript know that the variable I set, in this case I used indexCounter, that it’s referring to a range if I never defined a range?

I am assuming n++ is just short hand for n = n + 1. Am I correct?

I am so lost, the author creates a variable called output.
Why? Why is the variable empty? How does an empty string and a number generate any sort of output?

Then he does…

if (n % 3 == 0) output += "Fizz";
if (n % 5 == 0) output += "Buzz";

The way I read that is…

If (expression result) * output += “Fizz”?

What is “+=” ?

I have no idea how that works. Output is null/nill, it’s just an empty string.
How does the result of the previous expression and the variable output even do anything with each other as they are two totally different value types? Better yet, how are they even interacting at all?

Then the author uses this line… console.log(output || n);

Console.log( output or n ) is how I read that. I don’t even know if that’s right or even why he did that. Lol. ( Bashes head into desk )

This is all extremely confusing and JavaScript is making me want to claw my eyes out. The syntax of the language is overly complex compared to others I’ve tried in the past and it’s seemingly for no reason. Yet the world at large has decided to make it the face of the web, which is making me question my faith in humanity. What sadistic group of people thought making JavaScript this integral part of the world wide web? I curse them, I curse them all. Lol.

3 Likes

Corresponding tweet for this thread:

Share link for this tweet.

2 Likes

Looking at your answer, the loop structure itself is pretty good and indexCounter will count from 1 to 100 running the block (between { and } symbols) for each value of indexCounter.

This isn’t a great place to be, when you get stuck like this you do really need to walk away for a bit, take a break and try come back with a fresh mind. Sometimes you will see the answer, other times you might need to ask for help, but continuing on when you feel like this is only going to make it worse. In terms of the actual problem, it is to do with your if/else. A couple of important things about if/else:

  • Only one part (branch) will be evaluated when its matching condition is true. It could be the if, it could be the else or it could be an else if.
  • Each of the possible conditions will be checked from top to bottom to determine which branch to run. Combined with the previous point, this means when multiple conditions are true then only the first branch with a condition which is true is run.
  • Else does not have a condition, it runs in the case that all previous conditions have evaluated to false.

The problem with your version is the sequence of conditions that are checked means the FizzBuzz case can never happen. I’ll leave it as an exercise to work out how to fix this based on the points above, if you are still struggling I can help further.

I haven’t read the book so it is hard to comment much on the way the content is provided. It does feel like there are a couple of things in this solution that for a beginner in chapter 3 are adding some noise / confusion, regardless lets walk through the basic elements of what is going on here and address your questions.

So basically the for loop is a short hand for a common pattern and has become the idiomatic way to express that pattern. You are correct that the author is using n as the index counter, sometimes people frequently use “I” as a short name as well, you are also correct that n++ is a shorthand for n = n + 1. With those things in mind here is a while loop that has exactly the same semantic structure as your for loop here.

let n = 1; // initialise the start of the range before the loop
while (n <= 100) { // check the current value of n before entering the loop body if it is within 1-100
    /// do the stuff
    n++; // increment the counter at the end of the loop body to move to the next number in the range
}

What is happening in the for loop version is the 3 elements used to manage working through the range (the start, the check and the increment) are brought together in the for loop version. This makes the for loop version much easier to see that it is working over a range and what that range is.

The += is another one of those short hands similar to ++. It combines the plus and the assignment together so output = output + "Fizz" and output += "Fizz" are the same. Also + when used on numbers does addition, but when used on strings (like here) joins them together (concatenates).

You seem to roughly understand this correctly. It is really common to see in javascript but is not something I’d personally throw at a beginner. To go a little bit deeper into this, many things in javascript are not true/false but are often “truthy”. If you do a comparison with === or !== then it is strictly comparing true/false values but in most other cases if it has a value then it is interpreted as true and if it does not then it is interpreted as false. In particular, empty strings are considered false, 0 is also considered false, while a string with some letters in it "hello" is considered true and a number other than 0 is also considered true. In addition to this fuzzy version of true and false, javascript also doesn’t care much about types of values and will in many cases try to force the type of a value into one that works. So this output || n thing evaluates to the value of output if the value of output is truthy or the value of n if the value of n is truthy and the value of output is not, otherwise it evaluates to false. The result of evaluating output || n is used as the input to the console log. A clearer way of writing this particular example would be something like:

if (output) {
    console.log(output);
} else {
    console.log(n);
}

Lets go through this authors loop with some comments…

for (let n = 1; n <= 100; n++) // starting at 1, run the block (from { to } ) for each number n up to and including 100
{ 
  // for this particular n
  let output = ""; //  start with an empty output string
  if (n % 3 == 0) output += "Fizz"; // if this n is divisible by 3, join "Fizz" to the output string
  if (n % 5 == 0) output += "Buzz"; // if this n is divisible by 5, join "Buzz" to the output string
  console.log(output || n); // log the output if it isn't empty, log n if the output is empty
}  // move on to the next n

One thing of note beyond your questions here, unlike your version this author is using 2 independent ifs. Your version uses if with else if meaning only the if or else if will be run, but these two ifs will both be checked every time because they do not have else linking them together so they can both run if their conditions both evaluate to true. This means that when n is 15 for example, it can join both Fizz and Buzz to the output string.

You aren’t the only one that feels that way. What is worse is many of the things that create confusion or end up biting you pretty hard were actually intended to make it easier for people to get started with :man_facepalming: It is also worth remembering that it was intended to be easy to add fairly trivial little snippets to web pages and is now being used to build desktop class applications with many millions of lines of code. Along the way some things have improved, but the old things are still there and improvements have to work with them, so even though much of the evolution looks like improvements there is all kinds of hidden spicy bits in there.

3 Likes

Hi and welcome to the art of programming!

I started writing a longer answer but saw that @mindriot already answered. Like @mindriot I also think you got the looping right but were confused by the decision logic inside of it.

Programming can be quite abstract and it can sometimes help to try to reframe the problem into something more tangible. Maybe this helps or gives inspiration to future problems:

Say that you have a group of people in a large room and you want to give them each a clothing item depending on their color preferences. A red t-shirt with the logo Fizz if they like red, a blue hat with the logo Buzz if they like blue and both the t-shirt and the hat if they like both colors.

You put them in a line (the for loop) and start with the first person who happens to only like red. When asked “Do you like red?” and answer “Yes!”, the person is given a red t-shirt.

You then move to the next person and ask the same question:

“Do you like red?”
“No, I really don’t”
“Do you like blue?”
“I do!”

At this point a blue hat is given out and you move on to the next person again. The third person in line happens to like both red and blue and is looking forward to be given both a t-shirt and a hat. But when asked:

“Do you like red?”
“I do…”

Imagine the dissapointment when you hand out a red t-shirt and move on.

“If only they had asked the questions in a different order”, the third person mutters and reluctantly puts on the t-shirt.

Similarly, to apply the same metafor to the authors implementation. In this scenario instead of handing over the merchandise directly upon an affirmative response, the item is put in a bag (output) where multiple items can be put before handing it over.

Ie. something along the lines of:

  1. The questioner prepares an empty bag (let output = "").
  2. “Do you like red?”, “Yes!”. A red t-shirt is put in the bag. (output += "Fizz")
  3. “Do you like blue?”, “Yes!”. A blue hat is put in the bag. (output += "Buzz")
  4. The bag is handed over containing a red t-shirt and a blue hat.
    (console.log(output)).
5 Likes

(BASHES HEAD AGAINST DESK.)

I know this… Why didn’t I notice… UGH. I guess I should have just stepped away and came back to it. Ugh… Now I feel REALLY dumb. The author doesn’t mention it in his book but, I remember it from other books I’ve read.

What if I need to increment more than 1 at a time? Do I just add more + symbols? Or I just need to do the long form like n = n + 2?

I know about the arithmetic use and the concatenation use. But… The others…

output = output + “Fizz” to me makes perfect sense…

output += “Fizz”… That makes sense now that you’ve explained it. Wish the author explained it before using it. Lol.

What? You lost me.

I think I remember him mentioning this in the chapter I read.

The example I think he gave was something like this…

“dog” === “cat”
and it evaluates to false since the strings aren’t identical and it’s looking for an exact match.

“dog” !== “cat”
and it evaluates to true since they are the inverse of the previous example.

Did I remember that correctly?

0 is true and false? You lost me again.

The author mentioned this in the first chapter. So far it seems the info in the book is great it’s just the author’s examples that are causing confusion.

Yes! ok! That is much easier to understand and read. Kinda wish the author gave me that instead Lol.

Omg yes. COMMENTS! Why the author didn’t provide his example like that is beyond me.

Ok so anytime I am going to invoke a for loop I need to follow the following syntax…

for ( declare variable and assign a value ; ( Don’t really know what you would call this part ); Index Counter Increment. )

In the author’s example there are no if’s, did he use some sort of shorthand method or something?

Good to know I am not the only one. Lol. After I typed up my question I went to the ECMA’s website and downloaded the latest ECMAScript Language Specification and started reading the section on for loops. Lol.

Unfortunately, it seems they also have an issue with describing things in such a way that a non-engineer can actually understand what was written. Lol. I tried to read the syntax it provided but, it wasn’t very clear and they do not provide any examples so it’s difficult to understand what they are trying to say. I am sure if I read the spec from start to finish it would make sense but, right now, I just don’t have the time for that.

3 Likes

Great way to explain it. Thank you.

So, I would essentially be using the output variable to hold multiple answers if the index being checked meets multiple conditions.

Do I have that right?

2 Likes

You shouldn’t beat yourself up about it, it is very easy to overly focus on one part and completely miss what is really happening. Taking a break to clear your head is usually really helpful in this case. All of us have spent many hours b like this in the past, personally probably amounts to hundreds of hours.

You can use the arithmetic use of += for this, n += 2 or you can write the longer form if you prefer.

I probably shouldn’t have attempted to dive into this and try explain how it works… since we are in that hole now, I’ll give it another shot, if it still doesn’t make sense then don’t worry about it too much for now.

So what I’m talking about here is that there are true and false values which are explicitly true and explicitly false. There are also other values like 1 and "hello" which are neither true or false but can be treated as if they are in some cases, this is often known as “truthyness”. Looking at the slightly clearer if based version of printing the output or n, the use of output as a condition of the if here is depending on the fact that an empty string will be treated as false and conversely a non-empty string will be treated as if it is true.

 if (output) { // <-- when the output here is empty then it behaves as if output is false, if it is not empty it behaves as though it is true
    console.log(output);
} else {
    console.log(n);
}

You can even see this in a simple comparison, "" == false will evaluate to true, "hello" == true will also evaluate to true. The === and !=== versions I mentioned before don’t do this, "hello" === true is false. The version the original author had with output || n is depending in the same way on this implicit way that some values will treated as if they are true and others will treated as if they are false.

You did remember it correctly. These comparisons have 2 versions, these (which have 3 symbols) do a strict comparison that avoids mangling the types of the values and don’t let values pretend to be true/false. They have (generally best avoided) versions with 2 symbols, == and != which are less strict and do mangle types of values.

Sorry for adding to the confusion here. So in this situation that we are discussing where there is a number that is being used in place where a boolean value is expected and it is not a strict comparison (using === / !==) then 0 will be treated as false, other numbers will be treated as true. Here are a couple of examples:

let n = 5;
if (n) {
    console.log("n is not zero");
} else {
    console.log("n is zero");
}

prints “n is not zero”

where as

let n = 0;
if (n) {
    console.log("n is not zero");
} else {
    console.log("n is zero");
}

prints “n is zero”.

The middle part is the stop condition. It should answer the question “should this loop run for the current value of the index counting variable?” with a true or false answer.

We might not be talking about the same code or it might be the way it is formatted. In that part I was meaning about the way the if constructs are used in this code at the start of the commented lines.

for (let n = 1; n <= 100; n++) { 
  let output = "";
  if (n % 3 == 0) output += "Fizz"; // if is at the start of this line
  if (n % 5 == 0) output += "Buzz"; // if is at the start of this line
  console.log(output || n); 
}  

Here is the same code formatted slightly differently that might make the if construct more obvious.

for (let n = 1; n <= 100; n++) { 
    let output = "";
    
    if (n % 3 == 0)
        output += "Fizz";

    if (n % 5 == 0)
        output += "Buzz";
    
    console.log(output || n); 
}  

The main point was that early in the reply I made some comments about how if, else and else if behave in relation to what was going wrong with your solution. I wanted to clarify that those points were not applicable to the authors solution because these are two completely separate if constructs not linked with else or else if. Does that make more sense?

Language specs generally aren’t aimed at beginners, they are mainly a technical reference for people who already have a pretty good grasp on programming and usually are needing to double check a fine detail or are trying to implement a compiler/interpreter for the language.

3 Likes

Yes, in the case of FizzBuzz you need to ask the questions in the right order and concatenate the strings. But the same flow is common enough that it is good to be able to spot it when you see it:

  1. Initialize the a variable to hold the result
  2. Manipulate the variable in a number of steps
  3. Return the variable

The initial value and the manipulations will be different depending on what problem you are trying to solve but the generalized flow will be the same.

3 Likes

Thank you, you cleared up a LOAD of confusion. I am back on track.

Hope you all are having a nice Christmas day.

3 Likes

Thank you so much. Like mindriot you helped clear up things and have placed me back on track.

Hope your Christmas day is going well.

3 Likes

I have another question for you guys, it’s along the same lines as before…

Eloquent JavaScript
https://eloquentjavascript.net/

The problem goes like this…

Chessboard
Write a program that creates a string that represents an 8x8 grid, using new line characters to separate lines. At each position of the grid there is either a space or a # character. The characters should form a chessboard.
Passing this string to console.log should show something like this (Ignore the hyphens):


- # # # #- 
-# # # # - 
- # # # #- 
-# # # # - 
- # # # #- 
-# # # # - 
- # # # #- 
-# # # # -

This was how I did it…


  let _8x8_chess_grid = " # # # #\n# # # # \n # # # #\n# # # # \n # # # #\n# # # # \n # # # #\n# # # # ";

      console.log(_8x8_chess_grid);

The next part goes something like this…

When you have a program that generates this pattern, define a binding called size = 8 and change the program so that it works for any size, outputting a grid of the given width and height.

I am at a total loss. I’ve re-read the previous chapters again. I am still at a loss and I am refusing to look at the author’s answer, at least for a day or so while I think about it.

I have no idea how to even break down this problem.

I have some variables and values but, I have no idea how I am going to generate a pattern.


      let size = prompt("Please provide a number for the size variable to generate a grid in the console.log (F12).");
      let height = size;
      let width = size;
      let chess_grid_white = " ";
      let chess_grid_black = "#";
      let chess_newline = "\n";
      let chess_grid = "";
      let output = chess_grid;

I am at a total loss. I don’t know what to do.

I would appreciate help that doesn’t give me the answer but, nudges me into the right way of thinking to break down this problem so I can create a solution.

2 Likes

The problem has a fairly similar structure to the fizzbuzz one in many ways, think about what Hallski said and also think about what you learned about loops in the fizzbuzz exercise. It is a more complex version of the steps he laid out. First try thinking about how you can apply this pattern and use a loop to build a single row of a given size (it might be easiest to start with a grid all of black spaces first) then once you have achieved that you can think about using another loop to create the number of rows specified. After you have figured out how to assemble the grid structure, think about using the % similar to the fizzbuzz solution to get the alternate square colours right.

3 Likes

This was my solution…

// Declare all variables.
      let size = prompt("Please provide a number for the size variable to generate a grid in the console.log (F12).");
      let height = "";
      let width = "";
      let row = "";
      let column = "";
      let loop_index = 0;
      let chess_grid_white = " ";
      let chess_grid_black = "#";
      let chess_newline = "\n";
      let chess_grid = "";
      let output_chess_grid = "";


      /* Use loop construct to create a line that spans 
      the length of size variable and prints #'s accordingly to console output. */

      loop_index = 0;                                       //Use Loop index variable to keep track of progress through the loop.
      while (loop_index <= size) {                 // While loop index variable is less than or equal to size variable...
        chess_grid = chess_grid_black;             
        chess_grid_black = chess_grid_black + "#"; // Everytime we loop through, add another # until we meet our size requirement.
        loop_index = loop_index + 1;               // Advance the loop index and repeat loop until original condition is met.
      };

      loop_index = 0; // reset loop_index to zero.

      // output in console.
      console.log(chess_grid);

It’s generates…

#########

Now I just need to figure out the rest and refactor the solution to clean it up.

2 Likes

That is a good start. There are some opportunities to tidy up a little bit so it is good that you have spotted that. One fairly useful thing to keep in mind for the next step, you can have loops inside other loops. So you can have a loop that creates the rows and inside that have another loop that adds the squares together for to make each row ( like the one you have now).

2 Likes

So after a while of thinking about it and a trip to the store I’ve gotten to this point…

// Declare variables.
      let size = prompt("Please provide a number for the size variable to generate a grid in the console.log (F12).");
      let loop_index = 0;
      let chess_grid_white = " ";
      let chess_grid_black = "#";
      let chess_newline = "\n";
      let chess_grid_row_odd = "";
      let chess_grid_row_even = "";
      let chess_grid_final_output = "";

      loop_index = 0;

      console.log("You choose size as..." + size); // Just checking the variable before looping.

      // Using a loop for odd row generation.
      while (loop_index < size) {
        if (loop_index % 2 == 0)
          chess_grid_row_odd = chess_grid_row_odd + chess_grid_white;
        else
          chess_grid_row_odd = chess_grid_row_odd + chess_grid_black;
        loop_index = loop_index + 1;
      }

      console.log("final loop_index size for odd rows is " + loop_index); //Making sure the final index size is correct.

      loop_index = 0; // reset loop_index to zero.


      // Using a loop for even row generation.
      while (loop_index < size) {
        if (loop_index % 2 == 0)
          chess_grid_row_even = chess_grid_row_even + chess_grid_black;
        else
          chess_grid_row_even = chess_grid_row_even + chess_grid_white;
        loop_index = loop_index + 1;
      };

      console.log("final loop_index size for even rows is " + loop_index); //Making sure the final index size is correct.
      
      loop_index = 0; // reset loop_index to zero.
      

      //Take the now generated odd and even rows and generate the remaining rows.
      //Still trying to figure out how to do this.
      

      // output in console. Will eventually be chess_grid_final_output.
      console.log(chess_grid_row_odd);
      console.log(chess_grid_row_even);

      chess_grid_row_even = ""; //Resetting the variable.
      chess_grid_row_odd = ""; //Resetting the variable.

      console.log(" ");
      console.log("This ends the exercise!");
      console.log(" ");

It generates the following output…

Debug Output

2 Likes

OK thanks I got it.

This was my final solution. It’s not perfect but, it works.


// Declare all variables.

      /*
      declare size variable.
      do prompt toward user for size number over and over while user enters anything but a number.
      Something is broken here and I don't know what. It works the first time, after that it just enters an empty string.
      Can't figure out why.
      */
      let size;
      do {
        size = prompt("Please enter a number.");
      } while (size == NaN);
          size = prompt("Please enter a number.");



      let chess_grid_white = " ";
      let chess_grid_black = "#";
      let chess_grid_newline = "\n";
      let chess_grid_row_odd = "";
      let chess_grid_row_even = "";
      let chess_grid_final_output = "";
      let loop_index = 0;

      // Using a while loop for odd row generation.
      /* while loop index is less than size generate rows based on if branch.
      if loop index is divisible by 2 with no remainder, generate a white space.
      else generate a black space.
      concatnate and update odd row.
      move to the next loop index.*/
      while (loop_index < size) {
        if (loop_index % 2 == 0)
          chess_grid_row_odd = chess_grid_row_odd + chess_grid_white;
        else
          chess_grid_row_odd = chess_grid_row_odd + chess_grid_black;
        loop_index = loop_index + 1;
      }


      // Using a while loop for even row generation.
      /* 
      reset loop index variable.
      while loop index is less than size generate rows based on if branch.
      if loop index is divisible by 2 with no remainder, generate a black space.
      else generate a white space.
      concatnate and update even row variable.
      move to the next loop index.*/

      loop_index = 0; 
      while (loop_index < size) {
        if (loop_index % 2 == 0)
          chess_grid_row_even = chess_grid_row_even + chess_grid_black;
        else
          chess_grid_row_even = chess_grid_row_even + chess_grid_white;
        loop_index = loop_index + 1;
      };


      // Using a while loop for final output generation.
      /* 
      reset loop index variable.
      while loop index is less than size generate output.
      concatnate and update final output variable.
      move to the next loop index.*/

                                  
      loop_index = 0;                                                           
      while (loop_index < size) {
        chess_grid_final_output = chess_grid_final_output + chess_grid_row_odd + chess_grid_newline;
        chess_grid_final_output = chess_grid_final_output + chess_grid_row_even + chess_grid_newline;            
        loop_index = loop_index + 1;
      }


      //Resetting variable values.
      loop_index = 0;
      chess_grid_row_even = "";
      chess_grid_row_odd = "";
      
      // output in console.
      console.log(chess_grid_final_output);

      console.log(" ");
      console.log("This ends the exercise!");
      console.log(" ");

What do you think?

2 Likes

That’s awesome! It doesn’t have to be perfect, it is a learning exercise and getting it to work is the main thing. After that you can look for ways to improve but really in the early stages getting it to work is the biggest part.

The issues you are having with the prompt loop…

First the do … while construct will run the prompt at least once in every case and keep running it while the condition says so. This means you don’t need to prompt again outside the loop. This is better:

But it still won’t work as you expect it to because the problem is with the condition (size == NaN) for 2 reasons. The first reason is that size is never ever going to be NaN, NaN is a special value used to signal an error when doing math on something that is not a number type and cannot be converted into a number type or when it is an illegal math operation that cannot result in a number. Importantly NaN is a value, so you when you try compare values which are not numbers to the value NaN the result will be false because even though they are not numbers they are also not NaN. Secondly in a spectacularly confusing way, the value NaN is not equal to the value NaN so even if the value is NaN then NaN == NaN is false, so is NaN === NaN.

There are a few ways of doing what you are trying to do here, I’m going to focus on the one that is closest to the way you are trying to do it though it may introduce one or two functions you have not seen before (since I haven’t read the book, I’m not sure if these have appeared yet), so I’m not sure if it was what the author had in mind for this exercise or not. With that caveat out the way, the two functions we are going to use here are parseInt and isNan.

  • parseInt takes as its input a string (which is what we get from prompt) that may or may not contain a string representation of an integer number and tries to convert it to a number type, if it can then it returns the number it read from the string, if it cannot it returns our friend NaN. You can use it like this size = parseInt(someUserInput).
  • isNaN is a function that takes any value which may or may not be NaN and returns true if it is NaN and returns false for any other value (basically what you expect NaN == NaN to do in the first place).

Putting these together, this version should do what you are trying to do:

let size;
do {
    let input = prompt("Please enter a number.");
    size = parseInt(input);
} while (isNaN(size));

For the overall problem I had a slightly different solution. I’ve added it below to give you a chance to see another way to do it and see if you can work through how it comes together (I’ve added plenty comments to help), importantly I’ve not put it here to suggest it is a better solution or that your solution is in some way less right. There are a couple of things about how I have written my solution that I would like to highlight, these aren’t things super important for a beginner but they are super important overall and it is never too early to begin thinking about them when it comes to refactoring/tidying up your code just don’t get too hung up on them if they are getting in your way at this stage. So here is the solution I have:

// we have already discussed reading the input a fair bit so not much to add here
let size; 
do {
    let input = prompt('Please enter a number.');
    size = parseInt(input);
} while (isNaN(size));

// the symbols used for each type of cell never change so they are made constant here 
const blackCell = '#';
const whiteCell = ' ';

// the variable that we will gradually build up the grid into, it spans multiple iterations of the loop so needs to be outside
let grid = '';
for (let rowNum = 0; rowNum < size; rowNum++) { // loop size times to build up the right number of rows
    // by default make the even cells white and the odd cells black
    let evenCell = whiteCell;
    let oddCell = blackCell;

    if (rowNum % 2 == 0) { // every second row, switch the cell colors
        evenCell = blackCell;
        oddCell = whiteCell;
    }

    // the variable that we will build this row into
    let row = '';
    for (let colNum = 0; colNum < size; colNum++) { // loop size times to build the row width
        if (colNum % 2 == 0) { 
            row += evenCell; // add an even cell if the current colNum is divisable by 2
        } else {
            row += oddCell; // otherwise add an odd cell
        }
    }

    grid += row; // add the row to the grid
    grid += '\n'; // add a new line to the grid before starting the next row
    // evenCell, oddCell and row go out of scope here, there is no need to reset them they will be recreated
    // the next time through the loop.
}

console.log(grid);

The first thing to notice is that I’ve used const keyword for storing values that never change. One of the hardest things when reading or debugging code is keeping track of all the things which can change and where they are changing over time, every time you can reduce this overhead you make it much easier to work with code you have written. Using const clearly indicates that this value does not change over time and the reader doesn’t need to worry about that when they are keeping track of things.

Second thing, you sort of know this already but don’t seem completely comfortable yet… for loops are the more idiomatic way of writing loops that are based on an index counter. It is important to build your confidence with them soon, you don’t have to panic and stop all progress just keep in mind to spend a little time every few days to get more used to working with them.

Last thing, variables and scopes (this is a little more advanced in some respects). You will notice that when I create variables, I created them as close as possible to where I need to use them. This goes back to the keeping track of things changing over time point, the earlier you introduce them the more someone reading it has to keep track of. Variables created using let and const keywords are block scoped (in javascript blocks are groupings that start with a { and end with a }, they may be nested inside each other and the outer scope is visible in a nested block but a nested scope is not visible in the outer block), meaning they exist only up to the end of the block in which they are defined. Ideally you want variables defined in the smallest scope possible and as late in that scope as possible before you need to use it, this dramatically minimises the number of things to keep track of and allows the reader to know when they can forget about them. If you haven’t read much about scopes yet, don’t over think it just keep the general point in mind, if you have a good grasp of scopes then it would be a good exercise to see if you can improve your solution by reducing the “lifetime” your variables exist for. As a super advanced extra that you might see happen but really don’t have to worry about right now at all … You will see some javascript programs that create variables using the var keyword like this var size = 10;, these will (and should) use the style you have used of creating them at the start of the scope they belong to. var is a much older way to create variables, it has different scope rules and the interpreter does something called “hoisting” which means that if you define them in the middle of the scope it will move the definition to the start of the scope before running so in this case you should define them at the start to avoid confusion with how the interpreter will treat them. You won’t need to use var just now, if you are reading other peoples code though then you may see this happen and wonder why it is following a different style from what I am suggesting here.

2 Likes

I combined all my previous posts into a single post. I tried to delete the others but I am unable to do so. Only 1 delete allowed every 24 hours.

===============================================================================

Why would I use const when var or even let do the same stuff?

Is it simply to safeguard the value I assign it so that it can never be changed?

In what scenarios would it ever change though and how would it change?

( Still reading the rest of your post ).

Globals, local, etc. I haven’t read about it in this book, yet, or know how it works with JavaScript but, I do know scope refers to how the variable can be accessed by the program while it’s running.

Globals being dangerous as they can be accessed by anything. I also remember reading something about Globals to where if someone knows what the Globals are in your program they can somehow manipulate the values maliciously. From what I understand, locals can only exist inside the code block being executed, or something along those lines, and once the block is done, the variable is freed up. I also remember something about using locals is also preferred as it uses less memory while the application runs due to the fact the variables are created and freed up after each code block, while the Globals act similarly to constants and will maintain their usage of memory(RAM) until the program is closed and the memory is cleared.

Am I on track with that?

The author mentions var was the way to define variables in JavaScript pre2015 and that he will explain how it differs from let later in the book. He says we will rarely use it due some confusing properties of var. Chapter 2 page 25 I believe, under bindings.

https://eloquentjavascript.net/02_program_structure.html

The only reason I declared them at the start like that was it was a practice I picked up from an old book I read.

“Microsoft WSH and VBScript Programming, 3rd Edition for the absolute beginner.”

  • Jerry Lee Ford, Jr
    2009
    ISBN-10: 1-59863-803-3

The Author recommends to do the following and I found it sound advice, in hindsight… I am going to make some changes. Lol

It goes something like this…

The following would be entered as comments.

***************************************************************************
Program Name:
Author and way to contact them:
Year of Creation:
Description of what the program does:
The last time the program was altered and by who with contact info:
**************************************************************************
**************
Change Log
**************

***********
Variables
***********

***********
Functions
***********

*****************
Program Logic
*****************

But, I see your point. I should start to declare them right around where I am going to use them instead of setting them with a global scope. Lol.

I couldn’t figure out how to properly apply a for loop for my solution. It also didn’t sound right when I was reading it out load to myself to try and make sense of what was going on.

for this do this.

Every time I tried to apply a for loop the program would throw up some error as well. It didn’t like the way I typed it out my for loop and I couldn’t figure out why that was; So, I just moved on to using while loops as I was able to get them to work as intended. It also just read better when I was saying it out loud.

while this is happening, do this.

I will practice.

The author uses a lot of code examples that look like this…

num = prompt("Pick a number.");
if (num < 10) {
console.log("small");
} else if (num < 100) {
 console.lot("medium");
} else {
  console.log("large");
}

and it throws me off. Many of his for loop examples look similar and when I tried to follow along with his examples, they wouldn’t run, I would get an error complaining about brackets even though I was doing exactly what the author was doing. I couldn’t figure out why and then I bashed my head against the desk and started posting here. Lol.

I don’t get why it wouldn’t look something like this…


num = prompt("Pick a number.");

if (num < 10) 
{
console.log("small");

else if (num < 100) 
 console.lot("medium"); 

else
  console.log("large");
}
2 Likes

It does safeguard against changes. const is slightly different from constants in some other languages so if you have used something similar before then it might be more limited than it is in javascript. The basic rule with const in javascript is that you can only assign/bind to it one time and that time must be when it is being defined.

const hello = "world"; // <-- this is fine
hello = "void"; // <-- this throws an error because hello already has a value

const goodbye; // <-- throws an error because it must have an initial value

const name = prompt("What is your name?"); // <-- this is also fine, you don't have to know the value ahead of time but you can only set it once

When you use const you do get the safeguard of not being able to make the mistake of changing something that should never change, but you also communicate the intent that something should never change. Because you have both the intent and the safeguard the reader (which could be you later) has more information to help understand the code. As I previously mentioned the fact it doesn’t change reduces the need to keep track of it, but it also means that if the reader needs to check what value it has then there is only one place they have to look because after that it can never be set again. It is common in modern javascript to make really heavy use of const especially people who use React.

Yeah you are on track with that. If you haven’t gotten into scopes properly yet then don’t get ahead of yourself and worry too much about them yet, you can pick up what I was saying when you get there and hopefully it will help you make better use of them as you go forward.

var is pretty annoying in many ways, I mentioned it only because you might see it “in the wild” and due to its confusing properties people do use quite a different style to avoid some of the pitfalls of those. Not something to worry about now, only if you are looking at code and you see it then the code is very likely to be structured with all the variables for each function defined together.

It may or may not be good advice, some languages (or in the case of var language features) work quite differently and there may be good reasons to do this kind of thing. In general it used to be a very popular habit that has somewhat faded in favour of defining things close to where they are used but it does depend on how the language works. Most of the popular languages (i.e. ones you will find in the majority of job listings) have quite a bit of similarity and most of them will favour the style of defining things where they are used with ideally the smallest scope possible.

When I was first learning I also found the way for loops work to be really awkward. I always preferred to use while loops as like you they just made more sense to me. They are both equivalent to each other in this case and you can make a for loop by rearranging your while loop but it might feel a bit weird. Practise is important, you need to get used to them especially to make it easier to work with others (where using the more appropriate loop for the task is important) or read other peoples code more comfortably (where they will likely use for loops quite a lot, sometimes some pretty gnarly ones). Like I said before, take some time to work with them but also don’t bring yourself to a complete halt in order to only think about for loops just continue on slightly slower and spend a little time every day or two getting better at them. You can write while loops at the moment if you need to you just can’t ignore for loops forever.

If you are stuck / continue to be stuck, feel free to bring your code sample here and ask why you are getting an error (ideally if you say what the error is that is helpful too).

The brackets need to be balanced (matching number of opens/closes) and most of the time that there is a brackets problem then it is because there is one missing somewhere. It is also sometimes the case that an error can say that a bracket is expected when the problem is not the bracket itself but in fact an error before it has caused the interpreter to become confused about where the bracket should be. Again if you are still having problems, bring an example and we can try to work out what is going on.

If it were designed differently then it could look like that. One of the design goals was to make it have a similar syntax to the C family of languages, C/C++/C#/Java/Go and a bunch of others all have very similar syntax and it is very popular. In this style of syntax blocks are used to group together a collection of statements and expressions. The block starts with the opening { and ends with the closing }, in the block is a collection of related instructions. Blocks can be used in many places and work the same way everywhere they are used, they are used in if to define the chunk of code that should run with the condition is met, in loops to define the chunk of code that should happen on each iteration of the loop, in functions to group the chunk of code that is part of the function and in any other case where some part of the code needs to be wrapped in a boundary. If the design style was like your version then it wouldn’t work the same way all the time, it might need different constructs for each of the cases because for example a loop cannot have a else if randomly shoved into the middle of it. The structure being used here is something like this:

if ([condition])
    [block of code to execute when condition true]
else if ([other condition])
    [block of code to execute when other condition true]
else 
    [block of code to execute when everything else is false]

while([condition])
    [block of code to execute when condition true]

for([initialisation]; [condition]; [increment])
    [block of code to execute when condition is true]

function [name] ([parameters]) 
    [block of code to execute when called]

3 Likes

Long time no see. Just an update. I haven’t been home and just got back. I started reading the replies you left and moved on to the next chapter in the book, as per your recommendation to not get hung up on little things. The author goes into scope in Chapter 3 as well as functions. He kinda lost me with his words and jargon, thankfully I kinda already understand these concepts thanks to other books that explain it, as well as your assessment of my previous breakdown of the concept. I am going to re-read the chapter just to make sure I got everything he was trying to explain… Chances are I will bash my head in at some point and reach out to you once again, I hope you don’t mind. Lol. So far you have been an invaluable resource to me and my learning and it is greatly appreciated. I want to thank you for your replies. If you have any books of your own or have a class you offer, let me know, I would like to help you out. You are what I would expect a college teacher to be like except you actually try to help your students and teach them something of value rather than waste their time and money. Lol. Thanks for this breakdown of the syntax I’ve quoted from you. That snippet is invaluable to me. That is how I would expect a book teaching these types of things would/should explain new concepts to new people. This is what I was trying to find when looking up the EMCA spec as I’ve seen other specs do something similar and it’s a great way to show how to use syntax that makes sense and helps make it stick.

3 Likes