let example = {
a:20,
b:40,
c:60
}
for(let j=0,i in example){
console.log(example[i]*j);
j++;
}
Why normal for loop can have multiple variable declarations, but for-in loop cannot? Or am I doing this somehow wrong?
You're writing a code that's not syntactically correct.
in JavaScript you cannot use for-in expression with any other assignment expression.
You can simply pull out the j=0 assignment out of the for loop and that should fix the error
let example = {
a:20,
b:40,
c:60
}
let j=0
for(i in example){
console.log(example[i]*j);
j++;
}
[Edit] I have the found the following content in the official MDN site for the same scenario
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
As per the site - it's a publicly known issue that ChromeV8 and other browsers are trying to look into
For more info check the following references
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_for-in_initializer
https://bugzilla.mozilla.org/show_bug.cgi?id=748550
https://bugzilla.mozilla.org/show_bug.cgi?id=1164741
I can understand the frustration, you're using the same keyword so why doesn't it behave similar? But I think you should think about it this way:
for is a way to define a loop, for as long as some condition is true, with different way for how to define that condition.
In a regular for loop, you loop as long as the middle part (the condition) is true:
for(let i = 0; i < 10; i++)
This is similar to how a while loop might work, but it's a syntactic short cut:
let i = 0;
while (i < 10) {
i++;
}
So the for..in is a for loop that has another sort of condition, for every property in this object, so as long as you have more properties it will keep looping.
You could write that like this as well:
const keys = Object.keys(example);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = example[key];
}
You also have for...of, which loops over items in a array, but that is syntactic sugar for:
for(let i = 0; i < array.length; i++) { const item = array[i]; }
Also consider how a do...while loop is like a while loop but with some slightly different rules and behavior. Rather than getting frustrated with the syntax try to understand how it's saving you time by making your code a little less wordy, but in order to do that it needs to be a little different for each case. The alternative would be to have very many language keywords.
I tried changing your code to not declare any variables inside the parentheses of the for loop. I have never seen this done; maybe it's possible, but it would be simpler to declare a variable above the for loop, like this (assuming that's what you were hoping to do):
let example = {
a:20,
b:40,
c:60
}
let j=0
for(let i in example){
console.log(example[i]*j);
j++;
}
Edit: As mentioned in the comments: "You should probably add a let before the i declaration, otherwise it's going to be globally defined." I've just changed that in the snippet!
Related
I have value X that's supposed to be the "length" of what my loop should be (for example):
length = 10
I need to run a for loop to run length times. there's no object/array/anything I run on, nothing beyond the reference value length. is there a better way or cleaner way to write a for loop or to create a loop that runs length times in ES6 than this?
for(let i = 0; i < length ; i++)
An elegant way would be a generator for the indices:
function* range(from, to) {
for(let i = from; i < to; i++)
yield i;
}
for(const i of range(0, length)) /*...*/
But that's overengineering. A simple for loop is fine.
I don't think there is a strictly more elegant solution to that. You could write it like this
new Array(length).forEach(() => {
// do something
})
but if that's a more elegant solution is a matter of opinion.
I'm doing a tutorial on JavaScript. The following is from a section on performance:
Each statement in a loop, including the for statement, is executed for each iteration of the loop.
Statements or assignments that can be placed outside the loop will
make the loop run faster.
This is given as an example of bad code:
var i;
for (i = 0; i < arr.length; i++) {
And this is given as an example of good code:
var i;
var l = arr.length;
for (i = 0; i < l; i++) {
This is not something I can remember seeing as a best practice in languages that are more focused on performance than JavaScript. In fact, the bad code example seems to be preferred.
Is this best practice something particular for JavaScript, or is is true for other languages?
Bad Practice
for (i = 0; i < arr.length; i++) {
For every iteration in the loop, the condition is evaluated. If it is being arr.length then every time you are trying to access length property from arr. However, on the other hand, if you are storing it in a variable you are avoiding that operation.
Of all the ways to loop in javascript, the for-in loop is the safest in my opinion.
It can loop through the properties in an object.
let user = {first:"billy", last:"bob"};
for(let i in user){
console.log(i);
console.log(user[i]);
}
It doesn't throw an error if the variable is null
let empty = null;
for (let i in empty){
}
It works with arrays
let arr = [3,2,1];
for (let i in arr){
console.log(i);
console.log(arr[i]);
}
.map
.filter
.reduce
.forEach
throw errors with anything but arrays(null, objects etc)
So if you want one loop that works for everything, for-in is you what you want.
My teacher showed us this piece of code at the end of my cs class today and asked us to think about why it was not optimal.
Here is the code:
for (var x = 0; x < array.length; x++) {
console.log(array[x]);
}
I can't figure out what's wrong. I think maybe it is better to use a 'forEach' perhaps, but I'm not sure why?
Something like this?:
array.forEach(function(element) {
console.log(element);
});
You could probably just go with:
for(const el of array) { /*...*/ }
Why is that better? Well, you just need to look at it once, to get that it executes the block for every el of array. Its much faster to read than:
for(let i = 0; i < array.length; i++) {
const el = array[i];
/*...*/
}
And as programming languages are mainly there to be easily understandable by humans, you should always try to make the code as readable as possible. And it is also easier to spot bugs in the code if it is more readable, therefore increasing security, maintainability and development time.
By keeping the for loop, you could omit the different return value of postfix vs prefix syntax for the increment operator ++.
x++ // take value, then increment, slower
++x // increment, take value, faster
You should get the length into a variable rather than using it as array.length in the loop. ie.
var length = array.length.
for(let i = 0; i < length; i++)
What is the best practice for writing a JavaScript for loop?
I started out writing it like this:
for(var i = 0; i < array.length; i++){
//do stuff
}
But then I found that calculating the length on each pass is not ideal, so it should be more like:
var len = array.length;
for(var i = 0; i < len; i++){
//do stuff
}
But then the loop is faster if you decrease rather than increase:
var lenArr = array.length - 1;
for(var len = lenArr; len > 0; len--){
//do stuff
}
This kind of loop however doesn't really work if you want to break just one loop in a cluster of nested loops, so you should therefore get into the habit of using labels:
var lenArr = array.length - 1;
var lenArr2 = array2.length - 1;
loop1: for(var len = lenArr; len > 0; len--){
loop2: for(var len2 = lenArr2; len2 > 0; len2--){
//do stuff
break loop2;
}
}
Is there something else that will need to change, or is this the best practice for writing for loops in JavaScript?
IF you have array than make use of forEach
array.forEach(ele=> {
});
that way you can keep code clean and easy to understand and dont have to do length related code.
Break is not going to work with forEach but you can write return for coming out of forEach like
array.forEach(ele=> {
ele.array.forEach(ele=> {
//do stuff
return;
});
});
Note:
for loop is faster.
forEach is slower, but better fits functional programming paradigms.
Answer is based on title of question : Best Practice that why given suggestion to make use of forEach over for.
Actually, i prefer for...of as you can still break and its much less typing and its definetly more readable:
for(const el of array)
If you need indices too:
for(const [index, el] of array.entries())
Or if you need to iterate from back to front:
for(const el of array.reverse())
Concerning saving array.length: Even though in the early days of JavaScript it made a difference to save the .length value in a variable, modern JavaScript engines will run the for loop just as fast if you write it as in the first version.
Iterating backward is also not guaranteed to run faster on modern engines. There is also the consideration that CPUs are optimised to anticipate forward memory references, although this will only be relevant when the JS engine has decided to store the array as a contiguous block of memory.
As for the use of labels: most would not consider this best practice. Where the previous optimisation (concerning .length) concerns all iterations of the loop, this issue only applies to a single exit out of both loops. Whatever solution you use, it represents constant time, and could not be a determining factor in the overall performance of the loop.
So certainly in this case, I would go with good coding habits over tiny optimisation considerations. When you want to exit just the current loop, a single break is enough.
If you want to exit quickly from nested loops, then consider placing them in a function, so you can use return:
function performNestedLoop(array, array2) {
for(let i = 0; i < array.length; i++){
for(var j = 0; j < array2.length; j++){
//dostuff
if (exitCondition) return;
}
}
}
As to best practice: this really depends on what you need to achieve. There are several array methods that provide iteration, like forEach, map, reduce, reduceRight, filter, some, every, find, findIndex, includes,... each with their purpose. If they fit the purpose, then go with them. If you don't need the index, but just the value, then use for..of. If you really need every speck of optimatisation, then the old fashioned for loop is a likely winner.
You can use Array.forEach
Advantage of using forEach are as follows
Provides functional scoping, and whenever you need to perform some async function in the loop, you will not be required to created any IIFE
It keeps your code tidy and more contextual
Sample Code
arr.forEach(function(item, index){
// do stuff
});
I was just linting some JavaScript code using JSHint. In the code I have two for-loops both used like this:
for (var i = 0; i < somevalue; i++) { ... }
So both for-loops use the var i for iteration.
Now JSHint shows me an error for the second for-loop: "'i' is already defined". I can't say that this isn't true (because it obviously is) but I always thought this wouldn't matter as the var i is only used in that specific place.
Is it bad practice to use for-loops this way? Should I use a different variable for each for-loop in my code like
//for-loop 1
for (var i = 0; ...; i++) { ... }
//for-loop 2
for (var j = 0; ...; j++) { ... }
Or is this on e of the errors I can ignore (because it doesn't break my code, it still does what it is supposed to do)?
JSLint btw. stops validating at the first for loop because I don't define var i at the top of the function (that's why I switched to JSHint in the first place). So according to the example in this question: Should I use JSLint or JSHint JavaScript validation? – I should use for-loops like this anyway to confirm JSLint:
...
var i;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
...
//for-loop 2
for (i = 0; ...; i++) { ... }
This also looks good to me, because this way I should avoid both errors in JSLint and JSHint. But what I am uncertain about is if I should use a different variable for each for-loop like this:
...
var i, j;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
//for-loop 2
for (j = 0; ...; j++) { ... }
So is there a best practice for this or could I just go with any of the code above, meaning I choose "my" best practice?
Since variable declarations are hoisted to the top of the scope in which they appear the interpreter will effectively interpret both versions in the same way. For that reason, JSHint and JSLint suggest moving the declarations out of the loop initialiser.
The following code...
for (var i = 0; i < 10; i++) {}
for (var i = 5; i < 15; i++) {}
... is effectively interpreted as this:
var i;
for (i = 0; i < 10; i++) {}
for (i = 5; i < 15; i++) {}
Notice that there is really only one declaration of i, and multiple assignments to it - you can't really "redeclare" a variable in the same scope.
To actually answer your question...
is there a best practice for this or could I just go with any of the code above?
There are varying opinions on how best to handle this. Personally, I agree with JSLint and think the code is clearer when you declare all variables together at the top of each scope. Since that's how the code will be interpreted, why not write code that looks as it behaves?
But, as you've observed, the code will work regardless of the approach taken so it's a style/convention choice, and you can use whichever form you feel most comfortable with.
It has been mentioned only in the comment by #TSCrowder: If your environment supports it (Firefox, Node.js), in ES6 you can use let declaration
//for-loop 1
for (let i = 0; ...; i++) { ... }
//for-loop 2
for (let i = 0; ...; i++) { ... }
which limits the scope to within the for-loop. Bonus: JSHint stops complaining.
Variables in javascript are function scoped (not block scoped).
When you define var i in a loop, it remains there in loop and also in the function having that loop.
See below,
function myfun() {
//for-loop 1
for (var i = 0; ...; i++) { ... }
// i is already defined, its scope is visible outside of the loop1.
// so you should do something like this in second loop.
for (i = 0; ...; j++) { ... }
// But doing such will be inappropriate, as you will need to remember
// if `i` has been defined already or not. If not, the `i` would be global variable.
}
The reason JSHint shows the error is because in JS variable scope is function and variable declarations are hoisted to the top of the function.
In Firefox you can use let keyword to define block scope, but is not currently supported by other browsers.
The let keyword is included ECMAScript 6 specification.
I know this question has been answered, but if you want super for loops, write them like this:
var names = ['alex','john','paul','nemo'],
name = '',
idx = 0,
len = names.length;
for(;idx<len;++idx)
{
name = names[idx];
// do processing...
}
A couple of things going on here...
The array length is being stored in len. This stops JS evaluating names.length every iteration
The idx increment is a PRE-INCREMENT (e.g. ++idx NOT idx++). Pre-increments are natively faster than Post-increments.
The storing of a reference to name. This is optional but recommended if you'll be using the name variable a lot. Every call to names[idx] requires finding the index in the array. Whether this search be a linear search, tree search or hash table, the find is still happening. So store a reference in another variable to reduce lookups.
Finally, this is just my personal preference, and I have no proof or any performance benefits. However I always like initialising variables to the type they're going to be e.g. name = '',.
The best practice is to reduce the scope of variables, so the best way to declare iteration variable for the loops is
//for-loop 1
for (var i = 0; ...; i++) { ... }
//for-loop 2
for (var j = 0; ...; j++) { ... }
I know the scope of the variables declared with var but I am taking about code readability here.