javascript loops discrepancies for beginners - javascript

I wonder why seemingly equal loops lead to the different results.
First loop
for (var i = 0; i < 5; i++) {
console.log(i);
}
Results:
0
1
2
3
4
The result is fully understandable and expectable behaviour.
However, the following loop
var i=0;
while ( i<5) {
console.log(i);
i++;
}
leads to the different results, such that
0
1
2
3
4
4
As a beginner in programming I don't really understand why it is so, what the source of discrepancy in this case.

If you change to
var i=0;
while ( i<5) {
console.log("i is " + i);
i++;
}
then you will see in the console that it does output the correct values "i is 0", 1,2,3,4. The console also outputs the value of the last evaluated statement, which is why you see an additional 4.
If I run the for example in Google Chrome it prints an additional undefined because it outputs the value of the last evaluated statement, which is the console.log.

I think what you are seeing is an extra value printed by the interactive Javascript console that is the "result" of this code snippet.

The Javascript console prints the result of the for() and while() expression . If you run the first loop console :
for (var i = 0; i < 5; i++) {
console.log(i);
}
The results will be :
0
1
2
3
4
undefined
Here it prints the value of var i which is local to the scope of the for() loop , hence undefined outside it.
In the second case , just the var i is defined outside the loop body , hence it prints the latest value of i which is not undefined.

Since it seems the snippets are being evaluated, as through eval() or a REPL/Console, the extra 4 is the loop's return value.
And, yes, loops have return values.
Return (normal, V, empty).
Though, it's not something that's particularly useful to you in most cases, as attempting to retrieve it normally gives you a lovely SyntaxError. :)
var a = for (var i = 0; i < 5; i++) i;
console.log(a);
SyntaxError: Unexpected token for
However, eval() the loop, and you can see it.
var a = eval('for (var i = 0; i < 5; i++) i;');
console.log(a);
4
The value returned, V, comes from the evaluation of the loop's Statement. In the above case, that's simply i;, which is 4 the last time.
For your snippets, the for loop's result is undefined from console.log(i); and the while loop's result is 4 from i++;

Related

(javaScript) value in and out of 'for loop'

I am a beginner with javaSCript and just wondering why the results are different when it's called "inside" the loop and "outside" the loop.
for (var i = 0; i < 5; i++) {
console.log(i);
// prints 0 1 2 3 4
}
console.log(i);
// prints 0 1 2 3 4 5
Because the for looping steps is :
1 - define a variable,
2 - check the condition,
3 - run the code inside the loop,
4 - and increase the loop variable value by 1 ,
But! After defining the variable and After the first loop, it will ignore the first argument var i = 0 and it will increment the loop variable by 1, and check the condition, why? Because in the for looping, the last thing to do is increase the loop variable by 1,
So the last loop will increase the loop variable by 1 and check the condition ,
Simply: the variable has changed through the loop to 5 because after the first loop it will increase the variable by 1 and checking the condition
I hope my answer will be useful to you!
That's how var in JS works and also that's how for loops in all languages work.
When you declare a variable using var keyword it is hoisted to the function scope, or global if not inside a function. This lets you access var outside of the for loop scope. Try changing var to let and see what happens.
Secondly, you don't see 5 printed in the for-loop because of your condition i < 5. i++ causes 'i' to go from 4 to 5 which breaks the for-loop conditions and the 'i' is not printed.
Lastly console.log(i) outside the for-loop should just print 5 because that is the value of i at that point and not
console.log(i);
// prints 0 1 2 3 4 5
// should print 5
Inside the loop it logs the numbers from 0 to 4. The last i++ sets i to 5, and the loop stops because i < 5 is no longer true. Then the console.log(i) after the loop logs this value.
During the loop execution, the condition i < 5 fails for "5<5" but still the value of i here becomes '5' which is executed outside of the loop
for (var i = 0; i < 5; i++) {
console.log("inside loop: " + i);
// prints 0 1 2 3 4
}
console.log("outside loop: " + i);
// prints just 5

JavaScript - Factorialization 'For Loop' Understanding?

I am in the midst of completing some JavaScript algorithmic challenges and I had to factorialize a number as part of one of them. After searching through stack and other places I entered a correct code block:
function factorialize(num) {
if(num === 0) {
return 1;
}
if(num < 0 ) {
return undefined;
}
for(var i = num; --i; ) {
num *= i;
}
return num;
}
factorialize(5);
It it returns a correct result. What I am struggling to understand however is why the for loop doesn't have a second statement, and why it can run for ever? I have an inkling it's because as soon as i value is 0, any subsequent negative number that is generated will be multiplied by 0 and so only the integer numbers will form the result. But why does the function return a valid number, if the loop is still running to -infinity and hasn't been told to stop when reaching a certain value?
the second part of your for loop is the Condition:
An expression to be evaluated before each loop iteration. If this expression evaluates to true, statement is executed. This conditional test is optional. If omitted, the condition always evaluates to true. If the expression evaluates to false, execution skips to the first expression following the for construct.
Once --i reaches 0, it evaluates to false (falsey) and the for "exits"
adding a console.log(i) to your for loop will help demonstrate that
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
All elements in a for-loop's expression are optional.
The second part of the for-loop is used to express the for-loop's condition. The condition is evaluated on every iteration, and when it evaluates to false, the loop is exited.
In this case, that second part that expresses the condition is --i. This means that on every iteration, i will be decremented by 1, until it finally reaches zero (0). Since 0 is considered to be a falsey value in Javascript, the loop exits.
for (a; b; c)
is a direct equivalent to
a;
while (b) {
c;
}
You're mistaken here because you seem to think that c is what determines the end of the loop, but b actually is. You can omit the third loop statement if you don't need it (as well as the first one).
Here, your loop is equivalent to:
var i = num;
while (--i) {
num *= i;
}
while (--i) does two things:
Decrement i (before anything else)
Check that i != 0 (this is the actual loop condition).
If it was i--, note that the operations would be done in the opposite order.
If you find the code hard to read, you can also write it this way for the same results:
for (var i = num - 1; i != 0; i--) {
num *= i;
}
Normally you would have :
for(var i = 0; i < num; i++)
the second statement is a boolean continuation expression.
So when you have
for(var i = num; i--;)
The second is still a boolean continuation expression and when i get to 0 it evaluated to false.

Why does this code return undefined 4 times instead of the array values? [duplicate]

This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 7 years ago.
This is an example from a blog post by Avaylo Gerchev that addresses IIFE's. The following block of code returns 4 repeated 'undefined' responses by design:
function printFruits(fruits){
for (var i = 0; i < fruits.length; i++) {
setTimeout( function(){
console.log( fruits[i] );
}, i * 1000 );
}
}
printFruits(["Lemon", "Orange", "Mango", "Banana"]);
Avaylo then shows how to produce what (to me) would have been the expected output of the first code block (it outputs the values of the array):
function printFruits(fruits){
for (var i = 0; i < fruits.length; i++) {
(function(){
var current = i; // define new variable that will hold the current value of "i"
setTimeout( function(){
console.log( fruits[current] ); // this time the value of "current" will be different for each iteration
}, current * 1000 );
})();
}
}
printFruits(["Lemon", "Orange", "Mango", "Banana"]);
I understand that the IIFE creates a new scope. What I don't understand is the reason why the first block of code doesn't produce the (again, to me) expected output of returning the values in the array. I've been staring at this for a few days now, thus I conclude that my javascript knowledge is missing something fundamental.
Thank you for any insight!
In the first code block, the variable "i" is not accessible by the closure because setTimeout only defines what code to run but doesn't actually run it on definition, only later.
Having the closure there and running it immediately (with the parentheses () at the end) is a way to save the value of "i" in each iteration so that when setTimeout runs, it can access it.

How does javascript handle undefined comparators within for loops?

I recently fell victim to what I thought was an infinite for-loop in javascript, due to the following code.
//Mongoose Schema, defined elsewhere
var foo = new Schema({
_id: Number,
a: [ Number ],
b: [ Number ] });
...
//loop code, running on node.js server
Foo.findOne({}, 'b').exec().then(function(result)
{
if(result)
{
for(var i = 0; i < result['a'].length; i++)
{
...
//oops, we used the wrong property!
}
console.log("This line is never reached!");
}
}
Because foo doesn't have property bar, foo['bar'] is undefined, and the comparator never returns true (and ending the loop).
But what surprises me most about this code, is that it doesn't crash. So I was curious - did comparing a number to undefined always equal true? Because the program loops infinitely, I know the comparison doesn't return false.
In an attempt to test, I swapped the less than to a greater than, but I still never reached the console output. So what is going on? Why does this not cause a runtime error, and what, actually is getting compared?
Actually, if the foo object doesn't have a bar property, it will throw a TypeError, because you are trying to access a property of an undefined variable. This should halt the script execution.
var a;
a.length; //TypeError: a is undefined
Also, I made some tests and comparing undefined to a number using the < operator always returns false.
0 < undefined; //false
1 < undefined; //false
Following this logic, the following shouldn't loop and that's what happens in my case:
var o = {};
for (var i = 0; i < o.length; i++) {
console.log(i);
}
Perhaps your assumptions are wrong?

How to Call This Anonymous Javascript Function?

var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
return sum / arguments.length;
}
When I try to call this like:
var average = avg(2,3,5);
average; // It works fine;
But how do I call it without assigning to a variable?
If anybody can give any suggestion it will be delightful..Thanks.
You'd simply call it like this:
avg(2, 3, 5);
If you want to see the result, put it in an alert call:
alert( avg(2, 3, 5) );
You don't need to put the result from calling the function in a variable, you can do whatever you like with it.
For example, use it as the value in an alert:
alert(avg(2,3,5));
You can use it in another expression:
var message = "The average is " + avg(2,3,5);
You can use it directly in another call:
someFunction(avg(2,3,5));
You can even throw the result away by not doing anything with it, even if that's not useful in this specific situation:
avg(2,3,5);
If you don't put the result into a variable or in a compatible context, this function cannot output anything, which makes it difficult to use unless you make it output the result. Try this :
var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
var retvalue = sum / arguments.length;
consoloe.log("avg: "+retvalue);
return retvalue ;
}
Then it may help you to see whenever the function is called or not.
You need to understand the concept of expressions.
Every expression as a whole represents one value. An expression can be made up of multiple subexpressions that are combined in some manner (for example with operators) to yield a new value.
For instance:
3 is an expression (a literal, to be specific) that denotes the numeric value three.
3 + 4 is an expression, made up of two literal expressions, that as a whole yields the value 7
When you assign a value to a variable – as in var average = – the right hand side of the =-operator needs to be an expression, i.e. something that yields a value.
As you have observed, average will have been assigned the value five. It thus follows, that avg(2, 3, 5) must itself be an expression that evaluated to the value 5.
average itself is an expression, denoting the current value of said variable.
The most important thing to take away from this is, that avg() is in no way connected to var average =. avg() stands on its own, you can just think it like an ordinary value such as 5 (there are other differences of course).
If you have understood the concept of expressions and values, it should be clear that if you can do
var average = avg(2,3,5);
average; // It works fine;
You can also do
avg(2,3,5);

Categories