Using var to intentionally leak a variable - javascript

Is the following pattern ok in javascript, or is this frowned upon? And if the latter, what would be a better approach?
function arithmetic_sum(n) {
for (var [i, sum] = [0, 0]; i <= n; sum += i++);
return sum;
}
console.log(arithmetic_sum(10));
// 55

This is valid JavaScript.
Some people may like that, but it's a bit outdated and mixing old and new styles (var, but in combination with destructuring).
Also having code inside the interation clause of the for loop can be confusing.
I would prefer this instead:
function arithmetic_sum(n) {
let sum = 0;
for (let i = 0; i <= n; i++) {
sum += i;
}
return sum;
}
console.log(arithmetic_sum(10));
// 55

It really depends on the person to be honest. Some people will like this pattern because it makes the code shorter but in my personally opinion it makes the code harder to understand.
The reason this works is because of javascript hoisting. You can read more about this here.
https://www.w3schools.com/js/js_hoisting.asp
Now, if you were to switch this code to use let this code would break.
I think its also important to understand how var differs from let & const.
This article explained the differences very good
https://medium.com/#codingsam/awesome-javascript-no-more-var-working-title-999428999994
I personally would write this code like this:
function arithmetic_sum(n) {
let sum = 0;
for (let i = 0; i <= n; i++) sum += i;
return sum;
}
console.log(arithmetic_sum(10));
// 55

Related

Why does CoffeeScript compile to unidiomatic JavaScript?

I'm playing around with Coffee script (I'm new to this "language") and tried just a very basic example:
x = [1, 2, 3]
for element in x
console.log(element)
This does what it says, for each of the elements it outputs it to the console. It's only when I took a lot at the Javascript it compiled to that I can't understand why they do this:
(function() {
var element, i, len, x;
x = [1, 2, 3];
for (i = 0, len = x.length; i < len; i++) {
element = x[i];
console.log(x[i]);
}
}).call(this);
Would it not just be better and more natural to do:
for(i = 0; i < x.length; i++)
{
console.log(x[i]);
}
Why does coffee script compile to such a way that does not seem natural? If I was writing the same exact code in Javascript, I would follow the method that I did, but I might be wrong in that the way I did it (Javascript) is not the most efficient or "natural" and the coffee script method is a better solutions.
Basically you are expecting the CoffeeScript compiler to do acrobatics that would be really complicated.
Consider this CoffeeScript:
for a in x
console.log(a)
for b in a
console.log(b)
callFunc(b)
This transpiles to:
for (i = 0, len = x.length; i < len; i++) {
a = x[i];
console.log(a);
for (j = 0, len1 = a.length; j < len1; j++) {
b = a[j];
console.log(b);
callFunc(b);
}
}
It's very easy to see how the original CoffeeScript corresponds to the resulting JavaScript:
for [variable] in [array]
[body]
becomes
for (var [letter] = 0, len = [array].length, [letter] < len; [letter]++) {
[variable] = [array][[letter]]
[body converted to JavaScript]
}
So when translating a for comprehension into JavaScript, (almost) all the compiler needs to worry about is this simple correspondence, and then it can work inward and process the body as a separate and independent operation.
Also, the len = [array].length caching is done for performance. This isn't entirely pleasant to look at, and most people wouldn't code this way, but producing beautiful JavaScript is not the primary goal of CoffeeScript. It produces efficient code with the assumption that people won't generally be reading the generated JavaScript.
What you are suggesting is that it take that original code and turn it into:
for (i = 0; i < x.length; i++) {
console.log(x[i]);
for (j = 0; j < x[i].length; j++) {
console.log(x[i][j]);
callFunc(x[i][j]);
}
}
In order to convert console.log(b) into console.log(b);, the compiler doesn't need to know anything about the code surrounding that statement. In order to convert console.log(b) into console.log(x[i][j]);, the compiler would have to take everything around that statement into account. It would give the compiler an extremely complicated job to perform and wouldn't really provide any benefit.
Firstly, CoffeeScript builds everything in a closure by default, that would be these lines:
(function() {
}).call(this);
Closures prevent variables leaking out of the script. If you want to export your script as a global, then you need to explicitly attach it go a global, like window.
Next is the line:
var element, i, len, x;
It is considered good practice to declare your var's before using them (at least according to jslint).
Your definition of x of course:
x = [1, 2, 3];
Now the loop:
for (i = 0, len = x.length; i < len; i++) {
element = x[i];
console.log(x[i]);
}
Defining len first prevents the loop constantly looking up what x.length is. Not a huge speed difference with only three items, but an array with 10k, well...
The console.log is obvious, but the element variable is defined because that is the name of the variable you specified when you wrote your loop. And it uses i instead of element to iterate mostly because it's standard practice to use i for iteration.
So you see everything has a legitimate reason, albeit a little verbose for some tastes.

Add a value to each element in javascript

Is there a good way to add a certain value to each element in an array in javascript? Essentially, this should be a better way of writing the following:
a = [1,2,3,4];
for (i = 0; i < a.length; i++) {
a[i] += 7;
}
Maybe using map (but not necessarily)?
Edit:
Or a more interesting example:
a = [{'x':1},{'x':2},{'x':3},{'x':4}];
for (i = 0; i < a.length; i++) {
a[i].x += 7;
}
You can use map to do it:
a = a.map(function(entry) {
return entry + 7;
});
I'm not seeing how it's "better" to create a new array rather than update the one you have.
You can also use forEach:
a.forEach(function(entry, index) {
a[index] += 7;
});
It's still a bunch of function calls (but that's not a problem), but you have the advantage (over a for loop) of not having to declare the indexing variable, and you're modifying the existing array rather than replacing it.
Edit: Your "most interesting" example says even more that map is not really the best choice.
a.forEach(function(entry) {
entry.x += 7;
});
Yes, you can use .map but it will not modify the array in-place, so you must assign the result to a:
a = a.map(function(x) { return x+7 });

functions within loops, why are they considered an 'error'

For complex functions declared within a loop, I can see why I wouldn't want to do this, but why would it be be considered bad javascript?
We can name the function and place it outside the loop of course, but upsets the flow for something that is simple ( no async ).
Eg, below is a simple inline function declaration within a loop ( JSHINT/LINT complains, why this is considered a no no ?
for (var i = 0, len=arr.length; i < len; ++i) {
dosomething(arr[i], function(returnvalue) {
console.log(returnvalue);
});
};
Here's one reason why you wouldn't want that. The function references the same vars.
http://jsfiddle.net/RCzyF/
var a = [];
for(var i=0; i<10; i++) {
a.push(function () {
return i;
});
}
h = "";
for(var j=0; j<10; j++) {
h += "" + a[j]();
}
alert(h);
One could expect to see 0123456789 but it will append 10 10 times to h instead. It can make code really hard to understand when one function might change the content of other functions.
Here's a more complex example how things can get wrong.
var a = [];
for(var i=0; i<10; i++) {
a.push(function () {
return i++;
});
}
h = "";
for(var j=0; j<10; j++) {
h += "" + a[j]();
}
alert(h);
When the functions are created, they point to the same lexical scope. When the function are executed, they change the value inside the function and each function in the array still point to the same value. This can lead to really hard bug to debug when a variable gets modified but you didn't directly modify it.
Also here's the real answer coming from jslint itself: http://jslinterrors.com/dont-make-functions-within-a-loop/
Creating a function at each iteration is uselessly heavy.
Most of the time, in client side JavaScript, performance doesn't matter and there's no problem but it's better to take and keep good habits than having later to optimize the code (as long as the readability isn't hindered).
Here's a proof that you create a new function at each iteration :
var old;
function compare(_, a){
if (old) console.log('equal ?', old==a);
else old = a;
}
for (var i=0; i<2; i++){
compare(i, function(i) { return i*i });
}
It logs 'equal' ? false
testable jsbin

What is the most idiomatic way to handle variables declared in multiple for loops? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
JavaScript only has function scope. Thus, variables declared in for loops are visible for the entire function.
For example,
function foo() {
for(var i = 0; i < n; i++) {
// Do something
}
// i is still in scope here
}
When we have multiple for-loops, this opens the question of how we handle the variables in these other for loops.
Do we use a different variable?
for(var i = 0; i < n; i++) { }
for(var j = 0; j < n; j++) { }
Or do we use the same variable but just assign a value (instead of declaring it)?
for(var i = 0; i < n; i++) { }
for(i = 0; i < n; i++) { }
Or declare i outside of the loops?
var i;
for(i = 0; i < n; i++) { }
for(i = 0; i < n; i++) { }
Or redeclare i?
for(var i = 0; i < n; i++) { }
for(var i = 0; i < n; i++) { }
All of these work (or at least they do on the latest versions of my browsers). JSHint doesn't like the last approach, though.
Is there an approach which is most idiomatic or otherwise preferable?
It really depends on who you're coding for. If you're coding for a company or contributing to a library you of course follow their style guide. I've seen all of these (expect the last) used in libraries. If you like the Douglas Crockford style you'll go with the second to last and place all your variables at the top of function scope (or jslint will shout at you).
Taking an example from the jQuery style guide:
This is considered Good style
var i = 0;
if ( condition ) {
doSomething();
}
while ( !condition ) {
iterating++;
}
for ( ; i < 100; i++ ) {
object[ array[ i ] ] = someFn( i );
}
While this is poor style:
// Bad
if(condition) doSomething();
while(!condition) iterating++;
for(var i=0;i<100;i++) object[array[i]] = someFn(i);
Anyway, because this is style I'm going to reference how several libraries write their for each loops:
jQuery uses the Crockford style in core as does lodash
Underscore js uses the last style as seen here. Mootools also uses this style
If your code is going to be minimized before you release it, it will not matter as minifiers will mangle it to pretty much the same end representation in the processing.
Using different variables we have no problems.
Reusing and reassigning makes the code less readable, and if we remove the declaration at a later time, we risk assigning i to something outside of the function scope.
Declaring i outside the loops, we have no problems.
Redeclaring will be an issue if your lint tool, IDE, etc complain.
So I would argue for the first or third option. If number of variables is a concern using the first option, then you are may be in need of a refactoring.
Another take that answers the question in a different way.
A function with multiple loops makes me suspicious because:
It may be doing too much and should be decomposed anyway, and
It may be better to write it more functionally and eliminate the index altogether (it's available in some each-/map-y functions anyway)
Another approach is to use iterator functions. For example, in modern browsers an Array will have a forEach method:
var items = ["one", "two", "three"];
var things = ["hello", "goodbye"];
items.forEach(function (item, index) {
// Do stuff
});
things.forEach(function (item, index) {
// Do stuff
});
If you're using older browsers (or custom collections), you can make your own iterator like this:
Array.prototype.forEach = function(callback) {
for(var i = 0; i < this.length; i++) {
callback.apply(this, [this[i], i, this]);
}
};
For more information see: Array.prototype.forEach()
Any variables declared within a function are interpreted as being declared at the beginning of the function. Doug Crockford argues that you should declare all of your variables at the first line of every function.
doSomething = function() {
var i, ... other variables ...;
...
for (i = 0; i < x; i += 1) {
...
}
...
for (i = 0; i < x; i += 1) {
...
}
}
This way the code reads in the same way it will be parsed by the javascript engine.

Variable definitions in nested for loops?

Some static languages like Java seem to have very special rules for variables defined in the first argument of a for loop. They are accessible only by the given loop, which makes them behave pretty much like javascript functions' local variables and arguments. I mean stuff like this:
class ForVariable {
public static void main(String[] args) {
for(int i = 0; i != 0; i++) {}
System.out.println(i); // Throws an Exception
}
}
Javascript doesn't behave like that, which makes nesting loops quite a messy business. My question is: Is it valid to declare variables in the subsequent loops via the var keyword? In other words - which of the following examples is valid?
for(var i = 0, j; i < 5; i++) {
for(j = 0; j < 10; j++) <do some stuff>;
}
OR
for(var i = 0; i < 5; i++) {
for(var j = 0; j < 10; j++) <do some stuff>;
}
Clearly it is wrong to declare a variable several times, which would make the 2nd example a no-go, but given the fact that the 1st example is the way loops nesting is done in most languages I know, I'm rather hesitant to declare the winner.
Those are both valid. Function scoped vs block scoped. Basically both loops in JavaScript become:
function a () {
var i, j;
for(i = 0, j; i < 5; i++) {
for(j = 0; j < 10; j++) <do some stuff>;
}
}
because the var declarations are hoisted to the top
Its not wrong to declare a variable several times. For instance there is really no problem with:
var i = 0;
var i = 1;
That's valid JavaScript. Good tools like the Closure Compiler will generate a warning though because you typically don't intend to do that.
That being said, even the Closure Compiler won't generate a warning for your example #2. It's just common convention in JS even if you are technically re-declaring.
Either of your two examples is fine but the second one is a little more sensible to parse. I wouldn't worry about it either way.
You don't want to be using the var keyword, but rather function arguments, because javascript is not block-scoped. For example:
[100,200,300].forEach(function (x,i) {
[10,20,30].forEach(function (y,j) {
console.log('loop variables, indices '+[i,j]+' have values: '+[x,y]);
});
})
or
[100,200,300].map(function (x,i) {
return [10,20,30].map(function (y,j) {
return x+y;
});
})
// result: [[110,120,130],[210,220,230],[310,320,330]]

Categories