Javascript prints value in loop though the print is outside the loop - javascript

This question was asked before: Trouble understanding what happens during javascript for loop
but the asker didn't get the right answer and so did I. I learn C++ and Python earlier so I get familiar with loop but when I practing this code:
let text = "";
let i;
for(i=0; i<5; i++)
{text += "The number is " + i + " ";}
document.write(text);
the output is totally different to what I expected. I visited W3schools but I can't find the answer
https://www.w3schools.com/js/js_loop_for.asp
https://www.w3schools.com/js/tryit.asp?filename=tryjs_loop_for_om3
I expected the output is "" because text can't be changed but the code prints out: "The number is 0 The number is 1 The number is 2 The number is 3 The number is 4". My question is why the print executes in the loop though the print is outside the loop? Thank you very much!

The print executes as you expect: Only once at the end. In the loop, each time an extra part is appended to text. That is:
[iteration 0] ""
[iteration 1] "The number is 0 "
[iteration 2] "The number is 0 The number is 1"
[iteration 3] "The number is 0 The number is 1 The number is 2"
etc.
Then in the end, you print the final String which is the concatenation of all the partial Strings you 'glued' together.
Saying x += y is the same as saying x = x + y. Standard variables (var and let) are still mutable, so if you initialize it as an empty String, you can still append/replace it later.
Try making text a const instead, and there should be a runtime TypeError because you try to reassign a constant.

why the output not empty string because the text variable not empty anymore after for loop. you have assign string when loop so the text variable not empty anymore

Related

extra output after loop

I am learning JavaScript on Codecademy. I am finding so many outputs like below when I use while loop.
for (var i=0; i<5; i++){
console.log("Dhanu identify problems and solve them");
}
var loop = 0;
while(loop<5){
console.log("Do some more");
loop++;
}
I am getting an unwanted output in the last line as 4.
The output you get is simply console.log which logs the last known value of the 'loop' variable: (here in firefox):
It's absolutely not related to your code and you don't have to worry about that.
As stated in another answer, debug console use to log the result of the last line (probably because they are meant to debug).
For example the statement "i = 1" evaluates to "1":
while the statement "var i = 1;" evaluates to "undefined", hence logging "undefined"
you can observe the same behavior by invoking eval on those statements:
You're seeing that because the last statement in your while loop is loop++, which "returns" the current value of loop. This is just a side effect of running code in a console like this. Consoles are basically read-execute-print-loops (REPL), and so they need something to print. If you ran this as a script in a webpage you would not see 4
when you write any statement in developer console then last returned value will be printed...
for example
var a;
it prints undefined on console.
a = 10;
it prints 10 on console.
a = 10; a = a + 5;
it prints 15 on console.
simply when we assign any values or increment or decrement numbers then it returns value after performing that operation...
so, in the above or below code
var loop = 0;
while(loop<5){
console.log("Do some more");
loop++;
}
finally loop++ is 4.

How do I print While Loop?

Im trying to print the objects in my Array 'ana' but I keep getting a number 2 after the contents are printed. How do I remove the number 2?
var ana = ["I", "Love", "my mother"];
var a = 0;
mother = ana.length;
while(a < mother) {
console.log(ana[a]);
a++;
};
Logs:
I
Love
my mother
2
Don't worry. This is your interpreter behavior. Your code is not actually printing 2. You are seeing 2 because your javascript interpreter prints the value of last assigned value.
In your code, a++; executed in the last loop will return 2(because x++ returns x and then increments it) in the last loop thereby the return value of your whole expression is 2.
You must be printing 2 somewhere else after this loop, your code will only print 'I Love my mother'.. also, there shouldn't be any ; at the end of while loop.
See the demo here
You can move the a++ inside console.log to stop showing it. Like this
console.log(ana[a++]);
The value 2 was getting printed as the return value of your code, which is the last value that a gets.

understanding Javascript recursion

I am trying to wrap my head around recursive functions, and I do not understand the output (this example is from John Resig's 'Javascript Ninja' book):
var ninja = {
chirp: function chirp(n) {
return (n > 1) ? chirp(n-1) + "-chirp"+n : "chirp"+n;
}
}
$('#hello').html(ninja.chirp(8));
and the output:
chirp1-chirp2-chirp3-chirp4-chirp5-chirp6-chirp7-chirp8
Why is the output of n increasing instead of decreasing? It seems to me that the output would count down from 8 instead of up from 1.
http://jsfiddle.net/9xq7j6y8/1/
If you call chirp(1) the result will be "chirp1".
If you call chirp(2) the result will be chirp(1) + "-chirp2", i.e. "chirp1-chirp2".
If you call chirp(3) the result will be chirp(2) + "-chirp3", i.e. "chirp1-chirp2-chirp3".
As you see, the function calls itself to get the output for the lower numbers, and adds the highest number last.
It is counting down from 8, but the output is getting appended to the beginning of the string, and then you're reading the output from left to right.
If you saw the output as it was being built, it would look like:
-chirp8
-chirp7-chirp8
-chirp6-chirp7-chirp8
...
chirp1-chirp2-chirp3-chirp4-chirp5-chirp6-chirp7-chirp8
Since you only see the final output, it shows up in ascending order.

Custom function for Google Spreadsheet - handling the array passed from the spreadsheet

I am trying to build a simple script to work with a Google Spreadsheet. The spreadsheet takes input from a Google Form, so there is a series of values in the spreadsheet like this:
My goal is to write a script that would strip the number from each form input in a user-specified range, then add all the numbers to provide a single score. So, for example, the user could type =sumColumns(H2:K2) in a cell, and it would return the sum of the scores (for the sample screenshot I posted, it would return the result of 3+3+0+3, 9).
Here is the code that I wrote to do this:
function sumColumns(values) {
var sum = 0;
for(var i = 0; i <= values.length; i++){
var input = values[0][i];
var x = input.toString();
var y = x.charAt(0);
var num = parseInt(y);
sum += num;
}
return sum;
}
The problem is that it only ever seems to add two values together. So, when I put =sumColumns(H2:K2) in a cell in the spreadsheet, it only returns 6. Also, on line 3, if I change it from i <= values.length to i < values.length it only adds one number, so that I get 3 as a result. My guess is that I am misunderstanding the way that the Google Spreadsheet values are passed to the function, but I have been completely unable to make it work. I'd really appreciate any help!
Oops - edited & saved the question, wrote an answer - and forgot to save it. I let Serge beat me to it! And, as usual, Serge's answer works well (with integer values). But you did ask about how things worked, so here you go.
When you give a Custom Function a range as a parameter, H2:K2 in this case, the function receives a two-dimensional array, equivalent to the return value of Range.getValues(). You can test this easily, by (temporarily) changing your function to return a JSON representation of the parameter:
function sumColumns(values) {
return JSON.stringify(values); // For debugging, just return string showing values
...
Here's what you'll see in the cell that contains =sumColumns(H2:K2):
[["3 (Rarely)","3 (Frequently)","0 (Never)","3 (Frequently)"]]
That's showing an Array enclosed by [ .. ], with another Array inside, also enclosed by square brackets, and that array has four elements. If we change the range to be H2:K3 instead, we get this (with whitespace added for clarity):
[
["3 (Rarely)","3 (Frequently)","0 (Never)","3 (Frequently)"],
["","","",""]
]
Now that you know that, it's easy to see why your function was giving the results it did.
First, for(var i = 0; i <= values.length; i++) is using the wrong array bounds to loop over, since values.length will tell us how many rows are in values. In H2:K2, that length is 1. Instead, we need to be looping over the columns in the first row (values[0]), with its 4 cells.
You were wondering about < vs <= for this loop - we do need to use < since it's a 0-based index, and .length returns a count of elements. So we end up with:
for (var i=0; i < values[0].length; i++){ ... }
Using parseInt() is a good choice, and works well for the values in your spreadsheet. It can be improved, though, by ensuring that any String values have leading non-numeric values stripped first - parseInt() can then find an Integer inside a string.
function sumColumns(values) {
return JSON.stringify(values); // For debugging, just return string showing values
var sum = 0;
for(var i = 0; i < values[0].length; i++){
var input = new String(values[0][i])
.replace( /^\D+/g, ''); // Strip any leading non-digits
sum += parseInt(input);
}
return sum;
}
I'm not good with custom function because I never use them but it seems that values is not really an array...
Comments in italic :
Hmmm embarrassing ... my first though was that it had to be a 2D array but I logged val[0] in my test and it returned an 'undefined' error... I must have mistyped something at that moment... Anyway, that's why I looked for a way around handling data as a string and using split and regex.
As usual with Mogsdad's answers you have an answer and all the explanations that go with it ;-) and, as often with him too, you get a better answer than mine.
(one restriction though (#Mogsdad) your comment about non integer values could be applied to your code as well... you simply strip out any decimal value with parseInt()...:-)
That said, your use case was well described and in the limits of this example both code should work as expected, Mogsdad's one being more 'academic' and programmatically correct.
end of comment.
Using this trick below it works as expected for any input range (1 or more row and columns):
function sumCol(val) { // returns the sum of all numeric values in range
var values = val.toString().split(',');
var sum = 0;
for(var n=0;n<values.length;++n){
sum+=Number(values[n].replace(/[^0-9+.]/ig,''));
}
return sum;
}
I changed also the number extraction mode to make it more universal.

Javascript is not treating my counter variable as a number

I'm trying to generate form elements with jQuery to send to a Paypal form, I'm having issues looping through an array.
The list of items in a shopping cart is held in an array, the Javascript loops through the array adding the form fields and values as follows
for (j=0;j<(itemArray.length);j++)
$('#createFields').append("<input type='hidden' name='item_name_"+ j +"' value='"+itemArray[j]+"'/>");
This works perfectly, except, I need item_name_ to begin with a 1, not a 0.
"easy" I thought
for (j=0;j<(itemArray.length);j++)
$('#createFields').append("<input type='hidden' name='item_name_"+ j+1 +"' value='"+itemArray[j]+"'/>");
Should work, but no, that gives 01.
So I figured it wasn't treating "j" as integer
So I tried
(j*1)+1
That still gave me 01
parseInt(j)+1
Also gives me 01!
How can I get "0+1 = 1" from this counter variable?!
I can't understand why this issue is happening, I've got over the same problem with the methods above many times before!
I've also tried
for (j=1;j<( (itemArray.length+1) );j++)
but that just screws up the looping
Just group the expression:
"..." + (j+1) + "..."
this will give j + 1 a higher precedence so that it is evaluated first and then concatenated.
Otherwise, concatenation with the string will take place first, that is, first j is concatenated with the preceding string and then the resulting string is concatenated with 1 (left to right evaluation). Without grouping, the expression is implicitly evaluated as:
((("..." + j) + 1) + "...")
try
for (j=0;j<itemArray.length;j++)
{
$('#createFields').append("<input type='hidden' name='item_name_"+ (j+1)
+"' value='value='"+itemArray[j]+"'/>");
}
Another solution:
for (j=1;j<=itemArray.length;j++)
{
$('#createFields').append("<input type='hidden' name='item_name_"+ j +"'value='value='"+itemArray[j-1]+"'/>");
}

Categories

Resources