Explain JavaScript code process in plain English - javascript

I'm learning on Udacity and they have a quiz which I couldn't pass myself. I decided to look at the provided solution but I need to understand the process of the code (I understand some of it). Here it is:
// creates a line of * for a given length
function makeLine(length) {
var line = "";
for (var j = 1; j <= length; j++) {
line += "* ";
}
return line + "\n";
}
// your code goes here. Make sure you call makeLine() in your own code.
function buildTriangle(length) {
// Let's build a huge string equivalent to the triangle
var triangle = "";
//Let's start from the topmost line
var lineNumber = 1;
for(lineNumber=1; lineNumber<=length; lineNumber++){
// We will not print one line at a time.
// Rather, we will make a huge string that will comprise the whole triangle
triangle = triangle + makeLine(lineNumber);
}
return triangle;
}
// test your code by uncommenting the following line
// Note that the function buildTriangle() must return a string
// because the console.log() accepts a string argument
console.log(buildTriangle(10));
I understand that makeLine() will create line of asterisks based on the value of length that passed to it when it gets called inside buildTriangle()
But I don't understand how this line works:
triangle = triangle + makeLine(lineNumber);
Is it not working like the line in makeLine () which is
line += "* ";
What's the difference between using += and triangle = triangle + makeLine(lineNumber)? If they work same then the output should be wrong.
Also please correct me if I'm wrong in my understanding to the variable length in makeLine(length) and buildTriangle (length). Are they different variables because of different scope? Can I change the name of the variable in buildTriangle function to be something like buildTriangle (passedValueToMakeLineFunc)?
Finally it would be highly appreciated if someone imitate the JavaScript engine and described how it will handle that code step by step in plain English.

what's the difference between using += and triangle = triangle + makeLine(lineNumber)
These are equivalent:
triangle = triangle + makeLine(lineNumber);
triangle += makeLine(lineNumber);
…the variable length in makeLine(length) and buildTriangle (length) ... are they different variables…
Correct.
The variables are entirely independent and
you can call them whatever you want.
step by step in plain English
Apologies if this is too verbose or not what you had in mind:
declare functions makeLine and buildTriangle (define but do not execute)
invoke buildTriangle with a single argument (10) to resolve value to be passed to console.log
Execution of buildTriangle:
function buildTriangle(length) {
// Let's build a huge string equivalent to the triangle
var triangle = "";
//Let's start from the topmost line
var lineNumber = 1;
for(lineNumber=1; lineNumber<=length; lineNumber++){
// We will not print one line at a time.
// Rather, we will make a huge string that will comprise the whole triangle
triangle = triangle + makeLine(lineNumber);
}
return triangle;
}
begin execution of buildTriangle with length = 10
declare a variable called triangle with an initial empty string value
declare a variable called lineNumber with an initial value of 1.
initialize for loop: set variable lineNumber to 1 (again)
evaluate for loop condition. is lineNumber less than or equal to length (10)?
lineNumber is 1, which is less than 10, so loop condition is true. execute loop body.
evaluate makeLine(1) (lineNumber is 1)
Execution of makeLine:
function makeLine(length) {
var line = "";
for (var j = 1; j <= length; j++) {
line += "* ";
}
return line + "\n";
}
begin execution of makeLine with length = 1
declare variable called line and initialize to empty string
begin for loop: declare and initialize variable j with initial value 1
evaluate for loop condition. is j less than or equal to length (1)?
j is 1, which is equal to 1, so loop condition is true. execute loop body.
append "* " to line. (line is now "* ")
increment j. j is now 2.
evaluate for loop condition. is j less than or equal to length (1)?
j is 2. condition is false. exit loop.
return line value with a newline appended: ("* \n")
(Resume buildTriangle execution)
set triangle to its current value (empty string) plus resolved makeLine value: triangle is now "* \n"
end of loop body. run post-loop expression (lineNumber++)
set lineNumber to 2
evaluate for loop condition. is lineNumber less than or equal to length (10)?
lineNumber is 2, which is less than 10, so loop condition is true. execute loop body.
evaluate makeLine(2) (lineNumber is 2)
Execution of makeLine:
begin execution of makeLine with length = 2
declare variable called line and initialize to empty string
begin for loop: declare and initialize variable j with initial value 1
evaluate for loop condition. is j less than or equal to length (2)?
j is 1, which is less than 2, so loop condition is true. execute loop body.
append "* " to line. (line is now "* ")
increment j. j is now 2.
evaluate for loop condition. is j less than or equal to length (2)?
j is 2, which is equal to 2, so loop condition is true. execute loop body.
append "* " to line. (line is now "* * ")
increment j. j is now 3.
evaluate for loop condition. is j less than or equal to length (2)?
j is 3. condition is false. exit loop.
return line value with a newline appended: ("* * \n")
(Resume buildTriangle execution)
set triangle to its current value "* \n" plus resolved makeLine value: triangle is now "* \n* * \n"
end of loop body. run post-loop expression (lineNumber++)
set lineNumber to 3
evaluate for loop condition. is lineNumber less than or equal to length (10)?
lineNumber is 3, which is less than 10, so loop condition is true. execute loop body.
evaluate makeLine(3) (lineNumber is 3)
Repeat steps above until lineNumber reaches 11 and loop exits.
return value of triangle to caller and exit buildTriangle. At this point the value of triangle is:
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
invoke console.log with the value returned by buildTriangle.
exit
Your example included here for reference:
// creates a line of * for a given length
function makeLine(length) {
var line = "";
for (var j = 1; j <= length; j++) {
line += "* ";
}
return line + "\n";
}
// your code goes here. Make sure you call makeLine() in your own code.
function buildTriangle(length) {
// Let's build a huge string equivalent to the triangle
var triangle = "";
//Let's start from the topmost line
var lineNumber = 1;
for(lineNumber=1; lineNumber<=length; lineNumber++){
// We will not print one line at a time.
// Rather, we will make a huge string that will comprise the whole triangle
triangle = triangle + makeLine(lineNumber);
}
return triangle;
}
// test your code by uncommenting the following line
// Note that the function buildTriangle() must return a string
// because the console.log() accepts a string argument
console.log(buildTriangle(10));

Addition assignment operator (+=)
someVar += "someString" is the same as someVar = someVar + "someString"
Go ahead and replace your example with triangle += makeLine(lineNumber) and you'll see you get the same triangle.
The 2 lengths
In this case, they are both parameters to the functions makeLine and buildTriangle.
Function parameters are scoped to the function block, meaning they are only available inside the function, not accessible outside.
Name them as you like, this has no effect outside of the function block.
Note that if a length parameter did in fact exist outside of the function declarations, the length parameter would over/hide the external variable from use inside the function.
var length = 4;
console.log("outer", length); // 4
function someFunction(length) {
console.log("inner", length); // 5
}
someFunction(5);
console.log("outer", length); // 4
Code in english
I'm going to assume this is a little too detailed in some places and maybe not enough in others. Enjoy the story!
The makeLine function is declared (but not run yet)
The buildTriangle function is declared (but not run yet)
We hit a console.log() with a param of a function call (buildTriangle(10)). We'll execute that function, and the result of it will be passed to the log function call.
We've stepped into the buildTriangle function with a param length of value 10.
We make a triangle variable we'll build out the entire triangle into, new lines and all, initialized to an empty string.
We declare a lineNumber variable set to 1.
This one is just to mess with you
It did not need to be done before the for loop, would have been just the same to for (var lineNumber=1; lineNumber<=length; lineNumber++){ ... } and not declare it before hand.
It does not matter what it was or wasn't initialized to as the for loop sets it to 1 as it starts.
We hit a for loop, for(lineNumber=1; lineNumber<=length; lineNumber++)
We set lineNumber to 1
We will continue to run another iteration of this loop until lineNumber is <= length (10) (So up until and including 10)
We will, upon the completion of each iteration, before checking the continuation condition, increment the lineNumber by 1 (lineNumber++).
For each iteration of the loop (lineNumber values 1,2,3,4,5,6,7,8,9,10) we execute triangle = triangle + makeLine(lineNumber); Which just takes the current triangle string, appends the result of makeLine(lineNumber) to it, and assigns that value to triangle.
We've stepped into the makeLine function with a param length of value 1.
Note at this point, the only variable available to our scope is the length param. (Besides the 2 functions I suppose)
We initialize a new variable line to an empty string.
Note, this will be a brand new / separate line variable for every execution of this function Sounds like this is where you maybe hung up?
Since the line variable is declared inside the function, it is scoped there, and is not accessible outside or across function executions.
This would be different if it were declared outside of the function and not reset at the begining. Then every execution would continue to just add on.
We encounter another for loop, this time with the iterator variable declared inside (j) for (var j = 1; j <= length; j++) { ... }
We declare and initialize j to 1
We will continue to run another iteration of this loop until j is <= length (1) (So just 1 on this makeLine execution, subsequent times, 1-2, 1-3, ..., 1-10)
We will, upon the completion of each iteration, before checking the continuation condition, increment the j by 1 (j++).
For each iteration of the loop we execute line += "* "; which just takes the current line string, appends a "* " and assigns that value to line.
After this loop we encounter a return statement that is the result of combining our build out line with a newline character ("\n").
Assuming we've made it through all of our buildTriangle for loop iterations, we encounter our return statement and return the build out triangle.
We've now supplied the return value to be supplied as the parameter to console.log.
done.

Related

Understanding While Loops and Counter - How does it work?

Understanding While Loop
I am trying to understand what exactly happens when I use the 'while loop' to execute a code multiple times.
I was solving a problem on JSHero.net and I found it confusing so I tried explaining the solution to myself in order to get a clear understanding.
Please study the question, the answer and the simple explanation and let me know if I have understood it correctly. I could have done better explaining the counter as using it inside the condition itself confused me a lot.
Thanking all the good people in advance for helping me !!
Stay Safe !!
Question
Write a function spaces that takes a natural number n and returns a string of n spaces.
Example: spaces(1) should return ' '.
Answer
function spaces(num) {
let mySpaces = '';
while (num-- > 0)
mySpaces += ' ';
return mySpaces;
};
Explanation
declare a function spaces
it has 1 parameter 'num'
declare a variable mySpaces
initialize it with an empty string
we use a while loop as we need to repeat an action multiple times
in this case we need to add blank spaces to a string
our '''empty spaces string''' will be stored in the variable mySpaces
blank spaces will be equal to the 'num' parameter, which is fed when the function 'spaces' is called
while loops have: a condition and a code (loop body)
our condition is to ensure that the code should execute as long as the num is greater than 0
our condition is (num-- > 0)
our code is: mySpaces += ''
so if our function is called with the following parameter then how would this while loop work
spaces (3)
first it will check if 3 > 0; which it is and it will execute the code
mySpaces = mySpaces + ' '; the result in variable mySpace will now be ' ' (1 space)
then since we have used the num as a counter (num--), the loop will reduce 1 from 3 = 2
it will check if 2 > 0; which it is and it will execute the code
mySpaces = mySpaces + ' '; the result in variable mySpace will now be ' ' (2 spaces)
then since we have used the num as a counter (num--), the loop will reduce 1 from 2 = 1
it will check if 1 > 0; which it is and it will execute the code
mySpaces = mySpaces + ' '; the result in variable mySpace will now be ' ' (3 spaces)
then since we have used the num as a counter (num--), the loop will reduce 1 from 1 = 0
it will check if 0 > 0; which it is not and it will only execute the code after the while loop
we return the mySpaces variable which will give us the final result
While construction in javascript and most popular programming language consists of these parts:
while keyword
condition inside parentheses (num-- > 0)
body (mySpaces += ' ';)
It it used to repeatedly execute statements inside the body as long as condition is true.
For example this is how would you print Hello world repeatedly 5 times (please note, for this example for loop would have been more appropriate):
i = 5;
while (i > 0) { // as long as i is above zero
console.log("Hello world"); // print 'Hello world'
i--; // decrease value of i by one
}
In this particular example execution of while loop could be described as this:
check if condition is true
if not - skip body and continue with next statement after body
if yes - execute every statement inside body once and repeat this step
It is possible based on the condition that body gets executed zero, one, or multiple times.
In your code you start with some value of num, when you enter while loop, condition is checked, it is determined, whether body should or should not be executed and then num is decreased by one (because of the -- operator). This process repeats as long as num is above zero.
Slight modification in the order:
...
<> spaces (3)
<> a variable mySpaces will be declared and initialized with an empty string literal.
<> first it will check if 3 > 0; which it is and it start the loop. The value of num has already decreased by 1 in the memory, so now num = 2.
<> mySpaces = mySpaces + ' '; the result in variable mySpace will now be ' ' (1 space)
<> it will check if 2 > 0; which it is and it will execute the code. The value of num has again decreased by 1 in the memory, so now num = 1.
<> mySpaces = mySpaces + ' '; the result in variable mySpace will now be ' ' (2 spaces)
<> it will check if 1 > 0; which it is and it will execute the code. The value of num has again decreased by 1 in the memory, so now num = 0.
<> mySpaces = mySpaces + ' '; the result in variable mySpace will now be ' ' (3 spaces)
<> it will check if 0 > 0; which is false and it will not execute the code inside the while loop anymore. The value of num has again decreased by 1 in the memory, so now num = -1.
<> The last value of mySpaces which is ' ' (3 spaces) is returned from the function.
P.S. I've tried to write the answer in a way closest to how you've explained it. Hope this clears everything! Next time if you find the flow of code confusing always remember to put print statements at different places. Putting a console.log("Checkpoint 1") or printing the value of the variables in action greatly helps one to understand the changes as they happen. A more advanced way is to put breakpoints in code and debug. OnlineGDB's IDE makes a table of values for the variables and displays them at each stop.

Why is one of the following algorithms faster than the other if you do more processing?

function reverseString(str) {
let newStr = ''
for (let i = (str.length - 1); i >= 0; i--) {
newStr += str[i]
}
return newStr
}
// This algorithm is faster
function reverseString2(str) {
str = str.split('')
let left = 0
let right = str.length - 1
while (left < right) {
const tmp = str[left]
str[left] = str[right]
str[right] = tmp
left++
right--
}
return str.join('')
}
Why is reverseString2 faster than reverseString if the function does more processing, converting the string to an array and then concatenating the whole array? The advantage is that the main algorithm is O(n/2) but the rest is O(n). Why does that happen?
The results are the following:
str size: 20000000
reverseString: 4022.294ms
reverseString2: 1329.758ms
Thanks in advance.
In the first function reverseString(), what is happening is that the loop is running 'n' times. Here 'n' is meant to signify the length of the string. You can see that you are executing the loop n times to get the reversed string. So the total time taken by this function depends on the value of 'n'.
In the second function reverseString2(), the while loop is running only n/2 times. You can understand this when you look at the left and the right variable. For one execution of the loop, the left variable is increasing by 1 and the right variable is decreasing by 1. So you are doing 2 updation at once. So for a n-length string, it only executes for n/2 times.
Although there are much more statements in the second function, but they are being executed much less time than those statements in the first function. Hence the function reverseString2() is faster.

School assignment, i dont know what im doing wrong

can someone help me with this code for school, i just dont dont know what im doing wrong..
keep in mind..
Getal means: Number, and is already adjusted to all of the number of * in the console.
Resultaat means result.
Opdracht means Assignment
Here is my code,
Btw you can look at the test script, those answers is what it needs to be.
im only available to use, for loop, if statement, and a variable for the * it self aside from resultaat..
<script>
function opdracht(getal){
let resultaat = "*";
for (let i = 0; i < getal; i++){
resultaat += i + " "
}
return resultaat;
}
// Test script
test([-1], "*", opdracht);
test([0], "*", opdracht);
test([1], "*", opdracht);
test([2], "* **", opdracht);
test([10], "* ** *** **** ***** ****** ******* ******** ********* **********", opdracht);
It looks like the goal is to print a series of stars, increasing the number of stars until you reach the argument. Right now I'd guess you're getting "*0 1 2 ...". Without writing the whole answer out for you, I'd like to direct you to the string repeat method. "*".repeat(3) will get you "***". Use that inside the loop.
You need two nested loops; the first/outer one will add spaces ( ) between numbers and the second/inner one will print as many stars (*) as the current number you are considering.
Furthermore you have to take into account the fact that if the argument is < 2, you have to print just one star.
function opdracht(getal) {
// you initialize the result
let resultaat = '*'
// if the number is greater than 1...
if (getal > 1) {
// ... for each number btween 2 and the passed argument...
for (let i = 2; i <= getal; i++) {
// ... you add a space to the result and...
resultaat += ' ';
for (let j = 0; j < i; j++) {
// ... add as many stars as the current number is
resultaat += '*'
}
}
}
// finally you print the result
console.log(resultaat);
}
//tests
opdracht(-1);
opdracht(0);
opdracht(1);
opdracht(2);
opdracht(10);
The loops step by step
Consider the case opdracht(3):
you enter the outer loop:
resultaat is *
i is 2
resultaat becomes *
you enter the inner loop
j is 0
resultaat becomes * *
j becomes 1
resultaat becomes * **
j becomes 2 and you exit the inner loop
i becomes 3
resultaat becomes * **
you enter the inner loop
j is 0
resultaat becomes * ** *
j becomes 1
resultaat becomes * ** **
j becomes 2
resultaat becomes * ** ***
j becomes 3 and you exit the inner loop
i becomes 4 and you exit the outer loop
you use three arguments to function , though you havent defined them in function , read the documentation about js , this is very good resource to study js https://javascript.info/

Javascript if statement in while loop

Below you can find the code for creating random 8 numbers between 1 and 80. It puts the random numbers into the numbers array and writes into the divs. Code runs without any problem if it increments the x inside if brackets.
If I put the 'x++' outside of if brackets, after several run I found that sometimes it creates a same random number and finds inside the numbers array. Then it skips and that div comes empty.
What is the difference between incrementing x in if block and incrementing x outside if block ?
Inside the if block :
var numbers = []
var luckyNumber;
var x = 1;
while (x <= 8) {
luckyNumber = Math.floor(Math.random() * 80 + 1);
if (numbers.indexOf(luckyNumber) == -1) {
document.getElementById('k' + x).innerHTML = luckyNumber;
numbers.push(luckyNumber);
x++;
}
}
Outside the if block :
var numbers = []
var luckyNumber;
var x = 1;
while (x <= 8) {
luckyNumber = Math.floor(Math.random() * 80 + 1);
if (numbers.indexOf(luckyNumber) == -1) {
document.getElementById('k' + x).innerHTML = luckyNumber;
numbers.push(luckyNumber);
}
x++;
}
HTML:
<div id="k1">K1</div>
<div id="k2">K2</div>
<div id="k3">K3</div>
<div id="k4">K4</div>
<div id="k5">K5</div>
<div id="k6">K6</div>
<div id="k7">K7</div>
<div id="k8">K8</div>
When you put the increment outside the if condition, if there is a number already present in the numbers array, then it wont enter into the if condition and hence the div never fills up. However you move on to the next div, since you incremented the x value. If you put the x incrementation outside, the x values remains the same when the condition inside if not met, hence in the next iteration the condition may pass or its keep trying.
Execution flow
When you have increment inside if
1) Generate random number.
2) Check in is already generated, if yes skip it. // you see ? when skip no increment happens, because the increment inside the the condition.
3) Generate again and go to step 2.
When you have increment outside if
1) Generate random number.
2) Check in is already generated, if yes skip it. Increase x value to next. //** you see ? incrementing no matter you skip it or not.
3) Generate again and go to step 2.
Because in the first example you advance x only in the case if a unique random number has been generated.
In the second example you advance x regardless if the generated number was unique or not. So it could happen in this case, that out of the 8 times it tried (because that is your while condition), it generated only two unique random numbers, for example.
if you write x++ outside if it always increases by 1 ..and if you put inside if its clear that it increases when your condition is satisfied.. according to this you output may differ.
You could use do while loop for checking, if the number is already taken.
var numbers = [],
luckyNumber,
x = 1;
while (x <= 8) {
do {
luckyNumber = Math.floor(Math.random() * 80 + 1);
} while (numbers.indexOf(luckyNumber) !== -1)
document.getElementById('k' + x).innerHTML = luckyNumber;
numbers.push(luckyNumber);
x++;
}
<div id="k1">K1</div>
<div id="k2">K2</div>
<div id="k3">K3</div>
<div id="k4">K4</div>
<div id="k5">K5</div>
<div id="k6">K6</div>
<div id="k7">K7</div>
<div id="k8">K8</div>
incrementing outside, if block will execute without any condition.
But you are incrementing inside, if block will execute only in that condition is true.

Explain, please, these ++ and -- operations

Why this code outputs 3, not 2?
var i = 1;
i = ++i + --i;
console.log(i);
I expected:
++i // i == 2
--i // i == 1
i = 1 + 1 // i == 2
Where I made mistake?
The changes occur in this order:
Increment i (to 2)
Take i for the left hand side of the addition (2)
Decrement i (to 1)
Take i for the right hand side of the addition (1)
Perform the addition and assign to i (3)
… and seeing you attempt to do this gives me some insight in to why JSLint doesn't like ++ and --.
Look at it this way
x = (something)
x = (++i) + (something)
x = (2) + (something)
x = (2) + (--i)
x = (2) + (1)
The terms are evaluated from left to right, once the first ++i is evaluated it won't be re-evaluated when you change its value with --i.
Your second line is adding 2 + 1.
In order, the interpreter would execute:
++i // i == 2
+
--i // i == 1
i = 2 + 1
++i equals 2, `--i' equals 1. 2 + 1 = 3.
You're a little off on your order of operations. Here's how it goes:
i is incremented by 1 (++i) resulting in a value of 2. This is
stored in i.
That value of two is then added to the value of (--i)
which is 1. 2 + 1 = 3
Because when you use ++i the value of i is incremented and then returned. However, if you use i++, the value of i is returned and then incremented. Reference
++$a Increments $a by one, then returns $a.
$a++ Returns $a, then increments $a by one.
--$a Decrements $a by one, then returns $a.
$a-- Returns $a, then decrements $a by one.
Because you're expecting this code to work as if this is a reference object and the values aren't collected until the unary operations are complete. But in most languages an expression is evaluated first, so i returns the value of i, not i itself.
If you had ++(--i) then you'd be right.
In short, don't do this.
The result of that operation isn't defined the same in every language/compiler/interpreter. So while it results in 3 in JavaScript, it may result in 2 elsewhere.

Categories