A basic Javascript For loop - javascript

# http://jsfiddle.net/defencedog/rrKYW/
A recent observation has deeply embezzled my knowledge of js. Look at the code below:
var x = "";
function postbody() {
for (i = 0; i < 5; i++) {
x = x + "<sup>" + i + "</sup><br/>";
document.getElementById("posti").innerHTML = x;
}
}​
The above code's output is similar to that of the following & that is the thing vague to me
var x = "";
function postbody() {
for (i = 0; i < 5; i++) {
x = x + "<sup>" + i + "</sup><br/>";
}
document.getElementById("posti").innerHTML = x;
}​
the latter code must giv me a single (to be concise last value of x) output & not the whole iterated output?

Both snippets accomplish the same thing; The first snippet is just less performant as it overwrites the value 5 times as the string is built up instead of writing the final string once.
unrelated: i is an implicit global. use var.

both will cause a same result.
x = x + ...

Sure it does. You add new code to x in each iteration and then set it in the element. setting innerHTML overwrites the entire content of the element.
In the first loop, each iteration will overwrite the html of the element with a little larger html, but the final iteration is the one that overwrites it with the 'complete' value of x.
So the end results are the same, but the first one is quite a bit slower.

The two examples are identical because on the first the innerHTML is being overwritten on each iteration while the value of the variable x is being concatenated with the other strings. By the last iteration, the element's innerHTML will have x's total value.

Related

How does Javascript variable works?

Recently started learning Javascript.
Given an assignment for my class, to click a button (a number 10 is written on the button), and there has to be "Result = 55". (here all numbers from 0 to 10 are added)
To change words by clicking buttons, wrote code like this:
function myFunction(num) {
var p = document.getElementById("mydata");
for (var i = 0; i <= num; i++) {
sum = sum + i;
p.innerHTML = "Result = " + sum;
}
}
After submitting assignment for school, learned that had to add var sum = 0 above var p = document.getElementById("mydata")
However, do not understand what var sum = 0 means. As for looks already show when to begin and end calculating, feel like it doesn't have to be there.
var sum = 0; declares a local variable named sum, and sets its initial value to 0.
If you don't do this, when you do:
sum = sum + i;
the variable sum is initially undefined, and adding i to it results in NaN (Not a Number).
Some languages (e.g. PHP) automatically treat initialized variables as 0 in arithmetic expressions, but JavaScript doesn't do this, so you need to specify the initial value of the variable.
This has nothing to do with the way the for loop determines when to begin and end. It's about how to correctly add the numbers along the way.
It doesn't have to be before the p assignment, but it needs to be before the for loop.
Also, the line
p.innerHTML = "Result = " + sum;
doesn't need to be inside the loop. You should wait until the loop is done.

Javascript: attempting to fill an array with a prompt but prompt is not displaying

I am attempting to call a method that asks the user how many entries they would like to make into an array and then prompts the user for each entry. I know this is likely a simple error but I cannot tell why my prompt is not working.
<script>
function testScore(){
var numberofScores = prompt("enter the number of scores:","");
var scores = new Array();
var whichScore=1;
for(var i=0; i<numberofScores; i++; whichScore++){
score[i]=prompt("enter score "+whichScore+":");
}
}
</script>
<a href="" onclick="testScore()">
Start Test score script
</a><br>
A loop is configured with 3 sections and thus two semi-colons. You had whichScore++ in a 4th section after adding a third semi-colon. You could have added it to the end of the configuration with a comma. But, adding it to the loop body, and not part of the loop declaration is cleaner. That said, the variable is not even needed. Just use (i + 1) and note that we're not modifying i here, we're just using an offset of it for display purposes only.
Also, in the loop: score[i], needs to be scores[i] and your <a> element should have an href="#" instead of an empty attribute.
Lastly, don't use inline HTML event handling attributes as they:
Make the code more difficult to read and lead to code duplication.
Cause global wrapper functions to be created around your supplied
attribute value that alter the binding of this in your function.
Don't follow the W3C DOM Event standard.
Use .addEventListener() in JavaScript instead:
// When the DOM content is ready
window.addEventListener("DOMContentLoaded", function(){
// Get a reference to the hyperlink and create a click event handler for it:
document.getElementById("makeScores").addEventListener("click", testScore);
function testScore(){
var numberofScores = prompt("enter the number of scores:","");
var scores = new Array();
for(var i = 0; i < numberofScores; i++){
scores[i] = prompt("enter score " + (i + 1) + ":");
}
console.log(scores);
}
});
Start Test score script
Here is a JSFiddle using your code. You have a lot going on here
https://jsfiddle.net/tcoedqkf/
First off, your for loop needs to have a comma besides the increments (although for readability I would do it in the for loop)
for(var i=0; i<numberofScores; i++,whichScore++){
Your variable name in the for loop is incorrect (missing an S)
scores[i]=prompt("enter score "+whichScore+":");
<script>
function testScore(){
var numberofScores = prompt("enter the number of scores:","");
var scores = new Array();
var whichScore=1;
for(var i=0; i<numberofScores; i++, whichScore++){
scores.push(prompt("enter score "+whichScore+":"));
//or
//scores[i]= (prompt("enter score "+whichScore+":"));
}
}
</script>
<a href="" onclick="testScore()">
Start Test score script
</a><br>
your variable is scores
Use Array.push, since you did not declare the array length in array constructor. Edit : You can also use scores[i]. It will work as well.
for only have three sections (separated by a semicolon ;): initialization, the condition and the incrementation. If you want to initialize or increment more variables use a comma ,. Like this:
for(var i = 0; i < numberofScores; i++, whichScore++) {
// ...
Since whichScore is basically just i + 1 you won't need to have two variables for that, just i will do:
for(var i = 0; i < numberofScores; i++) {
score[i] = prompt("enter score " + (i + 1) + ":");
// ...
Note that the parenthesis in (i + 1) are necessary so the numbers are added instead of concatenated.

Closure in JavaScript from CoderSchool

I was doing some studying on CodeSchool. While watching a tutorial I was confused by an example. What they were trying to explain in the video was that closures created in loops won't bind until the last minute. The aim for this code was to take a name check for it in the array and return the name alone with its position(without the zero convention). Since closures don't bind till the last minute this code is returning z 5. I am confused why this code is returning a 5 and not a 4. The length of my array is 4 and the for loop stops before 4 because i < passengerArray.length which is the equivalent of i < 4 therefore the last index checked should be passengerArray[3] which means my (i+1) should be 4 in the end and not 5. I hope that makes sense. This has been bothering me all day.
function assignTorpedo(name, passengerArray)
{var torpedoassignment;
for(var i = 0; i < passengerArray.length; i++){
if(passengerArray[i] == name){
torpedoAssignment = function(){
console.log(name + " " + (i+1));
};
}
}
return torpedoAssignment;
}
var give = assignTorpedo("z",["z","a","b","c"]);
give();
The for loop ends when the test condition fails. Why does it fail? Because i is not less than 4; it's equal to 4. Thus, in the console.log() output you see 5.
Also, the statement
closures created in loops won't bind until the last minute.
is a strange way of describing how things work. As soon as the name is found in the array, the variable is assigned a reference to the constructed function. When assignTorpedo returns that value, the closure exists. In the closure, the value of the variable "i" is already 4.
The following statement increments i by 1 after each pass through the loop. So, after the fourth iteration i will be increased by one and tested against the condition again, and then it will fail.
var arr = ["z","a","b","c"];
for ( var i = 0; i < arr.length; i++ ) {
console.log( i );
}
console.log( i );
The For loop finishes when condition "i < passengerArray.length" being violated which i equals 4 at that time.
then console.log(name + " " + (4 + 1)));
Power Tip:
From one of my lecturers in uni,
"Think a "For" loop like a 'While' loop like this"
i = 0;
while (i < passengerArray.length)
{
...............
i++;
}

Javascript: Arrays and For Loop Basics

I'm new to javascript and have been trying to teach myself the basics. I do have some experience with C++.
I came across this example in the source I'm using for studying and the for loop looks strange to me:
<html>
<head>
<script type="text/javascript">
<!--
function ReadCookie()
{
var allcookies = document.cookie;
alert("All Cookies : " + allcookies );
// Get all the cookies pairs in an array
cookiearray = allcookies.split(';');
// Now take key value pair out of this array
for(var i=0; i<cookiearray.length; i++){
name = cookiearray[i].split('=')[0];
value = cookiearray[i].split('=')[1];
alert("Key is : " + name + " and Value is : " + value);
}
}
//-->
</script>
</head>
<body>
<form name="myform" action="">
<input type="button" value="Get Cookie" onclick="ReadCookie()"/>
</form>
</body>
</html>
Would someone mind explaining why there is a [0] and [1] near the end of these statements?
name = cookiearray[i].split('=')[0];
value = cookiearray[i].split('=')[1];
A clearer way to write this statement is this:
var parts = cookiearray[i].split('='),
name = parts[0],
value = parts[1];
That doesn't have anything to do with the for-loop itself. Split returns an array of tokens; the string is split up at the given delimiter. You're simply accessing the first and second tokens in this array.
String.split creates an array using the assigned delimiter (in this case '='). The [0] and [1] are selecting the first and second elements of the array respectively (Javascript array element indexes start at zero).
Those are used to access the items in the arrays that you create.
It's more clear what they do, and also better for performance, if you put the array in a variable and access that. That way you don't have to create two identical arrays:
var cookie = cookiearray[i].split('=');
var name = cookie[0];
var value = cookie[1];
The code is splitting each cookie pair key=value into key ([0]) and value ([1]).
A for loop is an iterator. You can sort of think of it like a counter, or stepping progression. If you want to do something x number of times, then a for loop is your best friend. The issue, when you are first learning, is figuring out how to use them effectively.
I'll give you a relevant and nonrelevant (simplified) example:
Nonrelevant:
// Increase the value of x and print the new value to the console 20 times.
var x = 6;
for(var i = 0; i < 20; i++) {
x++;
console.log("Value of x: " + x);
}
If you take a close look it's really rather logical. You define an iteration variable i, tell it when to stop (i < 20...so stop if i = 20), how to progress with each iteration (i++ or i + 1).
So the code will enter the loop when i = 0...it will add 1 to the value of x (x++), resulting in x = 7. It does the same for each iteration, so when i = 1, x (7) + 1 = 8, so on and so forth until i = 20, then the code breaks out of the loop and continues on it's merry little way. When it breaks we have just added 1 to x 20 times. Since x used to equal 6, it now equals 26.
Relevant:
// Given array of length 10, print each element to the console
for (var i = 0; i < cookiearray.length; i++){
console.log(cookiearray[i]);
}
So here the for loop is the same, it simply iterates until i equals the length (number of elements, in this case) of the array (so 10 times). When i = 0, our code prints the element of the array at cookiearray[0]...when i = 1 it prints cookiearray[1]...so on and so forth for the entirety of the array.
What may confuse you in the example is the split function. Split returns an array. So this line:
name = cookiearray[i].split('=')[0];
...actually means assign the first element of the new array created from splitting the cookiearray's element at position i.
Let's assume that cookiearray[0] = "Hello=World". When i = 0, our code splits the string "Hello=World" into a new array where the element at the 0 position is "Hello", it then assigns this to the local variable name. So name = "Hello".

let keyword in the for loop

ECMAScript 6's let is supposed to provide block scope without hoisting headaches. Can some explain why in the code below i in the function resolves to the last value from the loop (just like with var) instead of the value from the current iteration?
"use strict";
var things = {};
for (let i = 0; i < 3; i++) {
things["fun" + i] = function() {
console.log(i);
};
}
things["fun0"](); // prints 3
things["fun1"](); // prints 3
things["fun2"](); // prints 3
According to MDN using let in the for loop like that should bind the variable in the scope of the loop's body. Things work as I'd expect them when I use a temporary variable inside the block. Why is that necessary?
"use strict";
var things = {};
for (let i = 0; i < 3; i++) {
let index = i;
things["fun" + i] = function() {
console.log(index);
};
}
things["fun0"](); // prints 0
things["fun1"](); // prints 1
things["fun2"](); // prints 2
I tested the script with Traceur and node --harmony.
squint's answer is no longer up-to-date. In ECMA 6 specification, the specified behaviour is that in
for(let i;;){}
i gets a new binding for every iteration of the loop.
This means that every closure captures a different i instance. So the result of 012 is the correct result as of now. When you run this in Chrome v47+, you get the correct result. When you run it in IE11 and Edge, currently the incorrect result (333) seems to be produced.
More information regarding this bug/feature can be found in the links in this page;
Since when the let expression is used, every iteration creates a new lexical scope chained up to the previous scope. This has performance implications for using the let expression, which is reported here.
I passed this code through Babel so we can understand the behaviour in terms of familiar ES5:
for (let i = 0; i < 3; i++) {
i++;
things["fun" + i] = function() {
console.log(i);
};
i--;
}
Here is the code transpiled to ES5:
var _loop = function _loop(_i) {
_i++;
things["fun" + _i] = function () {
console.log(_i);
};
_i--;
i = _i;
};
for (var i = 0; i < 3; i++) {
_loop(i);
}
We can see that two variables are used.
In the outer scope i is the variable that changes as we iterate.
In the inner scope _i is a unique variable for each iteration. There will eventually be three separate instances of _i.
Each callback function can see its corresponding _i, and could even manipulate it if it wanted to, independently of the _is in other scopes.
(You can confirm that there are three different _is by doing console.log(i++) inside the callback. Changing _i in an earlier callback does not affect the output from later callbacks.)
At the end of each iteration, the value of _i is copied into i. Therefore changing the unique inner variable during the iteration will affect the outer iterated variable.
It is good to see that ES6 has continued the long-standing tradition of WTFJS.
IMHO -- the programmers who first implemented this LET (producing your initial version's results) did it correctly with respect to sanity; they may not have glanced at the spec during that implementation.
It makes more sense that a single variable is being used, but scoped to the for loop. Especially since one should feel free to change that variable depending on conditions within the loop.
But wait -- you can change the loop variable. WTFJS!! However, if you attempt to change it in your inner scope, it won't work now because it is a new variable.
I don't like what I have to do To get what I want (a single variable that is local to the for):
{
let x = 0;
for (; x < length; x++)
{
things["fun" + x] = function() {
console.log(x);
};
}
}
Where as to modify the more intuitive (if imaginary) version to handle a new variable per iteration:
for (let x = 0; x < length; x++)
{
let y = x;
things["fun" + y] = function() {
console.log(y);
};
}
It is crystal clear what my intention with the y variable is.. Or would have been if SANITY ruled the universe.
So your first example now works in FF; it produces the 0, 1, 2. You get to call the issue fixed. I call the issue WTFJS.
ps. My reference to WTFJS is from JoeyTwiddle above; It sounds like a meme I should have known before today, but today was a great time to learn it.

Categories