Should I really declare all vars in Javascript before using them? - javascript

Learning JS here, I run JSLint on this code:
/*jslint devel: true*/
function Animal(n) {
"use strict";
this.name = n;
this.prop = "a";
}
var a = new Animal("duppa");
for (v in a) {
if (a.hasOwnProperty(v)) {
console.log("property:" + v);
}
}
I get:
jslint:test2.js:11:6:'v' was used before it was defined.
jslint:test2.js:11:8:Cannot read property "kind" from undefined
jslint: ignored 0 errors.
It obviously complains that I did not declare v up front:
/*jslint devel: true*/
function Animal(n) {
"use strict";
this.name = n;
this.prop = "a";
}
var a = new Animal("duppa");
var v;
for (v in a) {
if (a.hasOwnProperty(v)) {
console.log("property:" + v);
}
}
This shuts JSLint up, but is it really necessary? In general I try to follow good conventions but is this one really necessary in JS? E.g. Python lives happily without such stuff (for x in range(10)... etc).

Yes, you absolutely should declare the variable. Otherwise you're declaring v at global scope which is never good, but it's particularly bad for counting variables which are a single letter long like v.
Consider the case where two people get lazy about declaring a variable of the same name:
// Your code, which iterates over a nested array
var arr = [ [1, 2], [3, 4] ];
for (i = 0; i < arr.length; ++i) {
AwesomeLibrary.doSomething(arr[i]);
}
// way down elsewhere, in awesome_library.js...
function doSomething(arr) {
for (i = 0; i < arr.length; ++i) {
// Now your `i` is clobbered, and we have a subtle but devastating bug
}
}
This doesn't even require two lazy people: If you work with JavaScript long enough and refuse to declare your variables, you will eventually do this to yourself.

There are 10 types of people in the world. Those who understand why you declare variables in javascript and those who have regular sex. (Just smile)
You must understand that every function have their own scope and you must use this scope. If you don't use declaration inside your function you change the global state, and it affects of course on many things.
So use var and don't create global variables !!!

It is always a better practice to define your variables before using them. Here javascript's for loop requires you to define i, because it is in the for loop, use
var v;
for( v in a)

As far as my understanding goes, if you use a variable without declaring it within a function scope, it gets declared in the global scope, which isnt a best practice. You will soon cloud your global scope with variables.
//This creates a global variable
function not_a_best_practice(){
a=10;
}
//This creates a local variable
function not_bad(){
var a=20;
}
This answer may throw more light on the discussion at hand:
What is the scope of variables in JavaScript?

Remember that JSLint doesn't complain because of some obscure academic reason but because it protects you from major problems your application may potentially suffer from.
You declare a variable to contain the variable in the current scope. It's a safeguard for you and your program as well making it more readable code (global vars appearing out of nowhere are always confusing).
Imagine if you had a global variable v in your application and then used the same nomenclature (v) for iteration in a function. Javascript will automatically assume that the global variable is being used and you'll find yourself with unwanted values in your global. Having said that, the less stuff you put in the global namespace the better.

Related

Is a variable declaration the same as a variable's binding?

MDN documentation states:
let bindings are created at the top of the (block) scope containing
the declaration, commonly referred to as "hoisting". Unlike variables
declared with var, which will start with the value undefined, let
variables are not initialized until their definition is evaluated.
Accessing the variable before the initialization results in a
ReferenceError. The variable is in a "temporal dead zone" from the
start of the block until the initialization is processed.
Is the "let binding" referrred to (the hoisting of let and const) just the keyword let, or is it just the creation of storage space (which doesn't have to do with the keyword)?
Previously I thought the variable keyword and variable name together comprised a declaration, but in a question I asked recently, the answerer said they are actually an initialization.
I'm sorry for using two different terms when writing that MDN paragraph. For all purposes in that article, "variable" and "binding" should be understood as the same thing. But let's go into details.
A variable declaration creates the variable (as an abstract entity). It tells the compiler that it should introduce a new variable, and also can tell it about a name, a type to be held, an initial value, a scope etc. (depending on the language). In JS, there are different kinds of declarations that do different things, for example
var has a name, an optional initialiser and scoping rules specific to var
function has a (sometimes optional) name, the value is always given and known to be a function
const has a name, a required initialiser, should be immutable, and has lexical scoping
…
A binding is the association of a variable name with the variable entity, for example "x refers to the variable declared with class x". Such bindings depend on the scope, i.e. in every different scope there are different bindings and so the identifier x might refer to different things in different scopes.
Given the scoping rules of JavaScript, a variable declaration also causes bindings for itself to be created in the respective scopes.
So the binding is what makes the name available to be used. That's what I referred to as "the let binding is created at the top of the scope". It has nothing to do with the variable existing, having memory allocated for it, or being initialised.
A declaration just says that something exists. In JavaScript you can declare variables, functions and (more recently) classes.
In some languages (e.g. C, C++) it's possible to declare something without defining it. For example:
// this declares a function exists with a given signature, but doesn't define its implementation
void someFunction();
someFunction(); // here we call the function, since we know it exists
// here we define the function, which we have to do at some point
void someFunction() { /* ... */ }
This pattern is less common in modern languages, where the declaration and the definition tends to be combined, but it's useful to understand the distinction seeing as your question seems largely about terminology.
Variables can be declared, however they don't have definitions.
let b; // we declare that there's a variable 'b'
Instead you can assign a variable:
b = 5; // assignment
let c = 6; // declaration and assignment in one statement
The concept of binding in computer science has many forms. For example, when you type foo in your code, binding is the act of working out which variable/function/type/... should be used. In JavaScript this is pretty straightforward, but in some languages it can get pretty hairy (due to things like overload resolution and so forth).
However I don't believe that's what MDN means when they talk about let bindings. I believe it's a shorthand for "let declaration and assignment", as we saw above.
Regardless, I wouldn't worry too much about that term. The most important bit to understand from the paragraph you've quoted is that let and const are tighter versions of var, introduced in recent versions of the language to address pitfalls and surprises that came from the way var works.
Previously I thought the variable keyword and variable name together comprised a declaration
You're right.
var a;
var b = 1;
let c;
let c = 2;
const d = 3;
These are all declarations of variables (even though const technical variables can't vary, or more precisely, they cannot be reassigned).
It's just that var is a bit sloppy and surprising.
You could declare a var more than once within the same scope:
var a = 1;
var a = 2;
This won't work with let:
let a = 1;
let a = 2; // SyntaxError: Identifier 'a' has already been declared
Scoping on var can be surprising too:
for (var i = 0; i < 10; i++)
{
var inner = 1;
}
console.log(inner); // prints 1 even though you might think this would be an error
Or worse:
for (var i = 0; i < 10; i++)
{
for (var i = 0; i < 10; i++)
{
console.log('hello');
}
}
At a glance you might think this would print hello 100 times (10*10), but actually it is only printed 10 times because both loops use the same variable. This is a type of programmer error that the language should really prevent. If that code used let i instead, it would produce a syntax error.
As for hoisting you can think of it as though all the var declarations were moved to the top of the containing function.
function foo()
{
doThing();
var i = 0;
doSomethingElse();
for (var j = 0; j < 10; j++)
{
var k = 10;
}
}
Even though that's how you might write the code, it behaves as though you had written:
function foo()
{
var i; // all declarations hoisted to top of containing function scope
var j;
var k;
doThing();
i = 0;
doSomethingElse();
for (j = 0; j < 10; j++)
{
k = 10;
}
}
This is why you can write:
i = 10;
var i;
The var is moved up in the code, so it behaves as:
var i;
i = 10;
You can think of let as not being moved. Therefore it is an error to reference it before it is declared.
The main thing to understand here is that the js engine actually visits a let statement inntwo different situations (as well as every other statement, but it particularily matters here). It is visited once during parsing, when it generates an AST and also analyzes the scopes and the variables. It also creates a list of variables for each scope. Now when the code gets executed, the engine visits the statement a second time (or more often if its inside a loop / function / whatever) and now finally initializes the variable and assigns a value to it. So "hoisting" is basically just caused because of the parsing / executing stages, the engine knows that a variable exists before it reaches the declaration statement during execution as it has already parsed it before.
Is the "let binding" referrred to (the hoisting of let and const) just the keyword let, or is it just the creation of storage space (which doesn't have to do with the keyword)?
The keyword actually causes an entry in the scope record, which will then get turned into a storage space during execution. On the other hand the statement itself causes an initialization during execution. So its actually hard to say when a declaration happens, thats a question of words. Its common to say
That variable was declared at line 10
Its declared in that block
so wether "declaration" refers to the statement or the scope assignment is up to you :)
the answerer said they are actually an initialization.
Actually the answerer prefered to call it "initialization" and not "declaration" to not confuse readers, but well in reality its confusing as human languages are not as clearly defined as machine ones.

Tool to guide manual de-minification of variables and functions?

I have a minified javascript file. I can send it through a variety of tools to insert newlines and indentation. What I then want is to fix the variable names. I know that no tool can do this automatically. What I need is a tool that will augment my attempt to do so manually. It needs to be aware of scope rules so that when I rename c to length and d to height and j() to move(), those changes will be made everywhere that the same c and d and j are used, but not in other scopes where different variables and functions with those same names exist.
Is there a tool like this, specifically designed for reversing minification? If there isn't a tool for this specific job, is there a smart IDE that can at least handle renaming variables or methods following scope rules?
I found an in-browser/downloadable node.js library tool that does rename refactoring very well. Esprima handles the following ES6 code (slightly modified from the example) such that when I change the name of any of the global scope hi, only the hi names surrounded by a comment block are changed (I couldn't think of a better way to call out code since markdown doesn't show in code blocks, sorry).
// Array shuffling code from Underscore.js, code modified from base example on http://esprima.org/demo/rename.html
var shuffled;
var /*hi*/ = 'hi'; // initial declaration
function /*hi*/() { // modifies var above
this.shuffle = 'x';
}
_.shuffle = function(obj) {
function hi() {
return 'hello';
}
var shuffled = [], rand;
each(obj, function(value, index, list) {
rand = Math.floor(Math.random() * (index + 1));
shuffled[index] = shuffled[rand];
shuffled[rand] = value;
});
hi(); // calls function defined above, name not changed by change to global scope 'hi'
console.log(hello); // considered to be the same as the let statement below even though this is a syntax error since let doesn't get hoisted like var
return shuffled;
};
let hello = 'hello';
function hiNotInScope() {
var hi = 'something else'; // not in global scope, so change to global hi doesn't change this
console.log(hi); // changed if the hi in this scope is changed
}
// hi (not changed since it's in a comment)
/*hi*/(); // calls global hi function.
It seems to respect scoping rules as long as there are no code errors (for example, a let declaration above a var declaration of the same name that gets hoisted above the let will be considered in-scope, but this is a non-issue since it's a syntax error).

Mutating key inside JavaScript's for..in loop [duplicate]

What's the correct way to write a for-in loop in JavaScript? The browser doesn't issue a complaint about either of the two approaches I show here. First, there is this approach where the iteration variable x is explicitly declared:
for (var x in set) {
...
}
And alternatively this approach which reads more naturally but doesn't seem correct to me:
for (x in set) {
...
}
Use var, it reduces the scope of the variable otherwise the variable looks up to the nearest closure searching for a var statement. If it cannot find a var then it is global (if you are in a strict mode, using strict, global variables throw an error). This can lead to problems like the following.
function f (){
for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2
If you write var i in the for loop the alert shows 2.
JavaScript Scoping and Hoisting
The first version:
for (var x in set) {
...
}
declares a local variable called x. The second version:
for (x in set) {
...
}
does not.
If x is already a local variable (i.e. you have a var x; or var x = ...; somewhere earlier in your current scope (i.e. the current function)) then they will be equivalent. If x is not already a local variable, then using the second will implicitly declare a global variable x. Consider this code:
var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
for (x in obj1) alert(x);
}
function loop2() {
for (x in obj2) {
loop1();
alert(x);
}
}
loop2();
you might expect this to alert hey, there, heli, hey, there, copter, but since the x is one and the same it will alert hey, there, there, hey, there, there. You don't want that! Use var x in your for loops.
To top it all off: if the for loop is in the global scope (i.e. not in a function), then the local scope (the scope x is declared in if you use var x) is the same as the global scope (the scope x is implicitly declared in if you use x without a var), so the two versions will be identical.
You really should declare local variables with var, always.
You also should not use "for ... in" loops unless you're absolutely sure that that's what you want to do. For iterating through real arrays (which is pretty common), you should always use a loop with a numeric index:
for (var i = 0; i < array.length; ++i) {
var element = array[i];
// ...
}
Iterating through a plain array with "for ... in" can have unexpected consequences, because your loop may pick up attributes of the array besides the numerically indexed ones.
edit — here in 2015 it's also fine to use .forEach() to iterate through an array:
array.forEach(function(arrayElement, index, array) {
// first parameter is an element of the array
// second parameter is the index of the element in the array
// third parameter is the array itself
...
});
The .forEach() method is present on the Array prototype from IE9 forward.
Actually, if you dislike declaration within for heading, you can do:
var x;
for (x in set) {
...
}
As mentioned in other answers to this question, not using var at all produces unnecessary side-effects like assigning a global property.
Use the one where you declare the loop variable with var. Implicitly declared variables have a different scope that's probably not what you intended.
for(var i = 0; ...)
is a commonly seen pattern but it's different from
for(int i; ...)
in C++ in that that the variable isn't scoped to the for block. In fact, the var gets hoisted to the top of the enclosing scope (function) so a local i will be effectively available both before the for loop (after the beginning of the current scope/function) and after it.
In other words, doing:
(function(){ //beginning of your current scope;
//...
for(var i in obj) { ... };
})();
is the same as:
(function(){ //beginning of your current scope;
var i;
//...
for(i in obj) { ... };
})();
ES6 has the let keyword (instead of var) to limit the scope to the for block.
Of course, you SHOULD be using local variables (ones declared with either var or let or const (in ES6)) rather than implicit globals.
for(i=0; ...) or for(i in ...) will fail if you use "use strict"; (as you should) and i isn't declared.
Using var is the cleanest way, but both work as described here: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
Basically, by using var you ensure that you create a new variable. Otherwise you might accidentally use a previously defined variable.
I think var is good for performance reasons.
Javascript won't look through the whole global scope to see if x already exists somewhere else.
From a general point of view, first version will be for an index that must live within loop's scope, while the other one would be any variable in the scope where loop's constructor got invoked.
If you're going to use loop's index inside for loop and this won't be required by others in next lines, better declare the variable with "var" so you'll be sure "x" is for loop's index initialized with 0, while the other one, if other "x" variable is available in this context, this will get overwritten by loop's index - that's you'll have some logical errors -.
I always use the block scoped let introduced in ES2015.
for (let x in set) {
...
}
Additional reading and examples

Will I have any problems if I declare the same variable multiple times?

So lets say I have some code:
//Javascript
var elements = [];
function addNumbah1(){
var i = 1;
elements.push(i);
}
function addNumbah2(){
var i = 2;
elements.push(i);
}
And that goes on up to addNumbah999(), is it bad form to declare the i variable every time? Will that break anything? Should I do:
//Javascript
var elements = [];
var i
function addNumbah1(){
i = 1;
elements.push(i);
}
function addNumbah2(){
i = 2;
elements.push(i);
}
Short answer: NO, JS hoists all variable declarations to the top of the scope, regardless of how many times you've declared them:
var i = 0
for (var i=0;i<10;i++)
{
var j = i%2;//declared 10 times, on each iteration
}
Will be translated to
var i, j; //i is undefined at this point in the code.
for (i = 0;i<10;i++)
{
j = i%2;//declared 10 times, on each iteration
}
In your first example, you're declaring i as a variable in a function's scope, which is what you must do to avoid cluttering the global scope. The memory these variables use is allocated when the function is called, and deallocated when the function returns (roughly, closures form an exception, but that would take us to far). Consider this:
var i = 10;
function someF()
{
var i = 1;
alert(i);
}
someF();//alerts 1 <-- value of i, local to someF
alert(i);//10, global i is unchanged
But if you were to omit the var:
function someF()
{
i = 1;
alert(i);
}
You'll see that 1 is alerted twice. If JS can't find a variable declaration in the current scope, it will look in the higher scopes until a var is found. If no variable is found, JS will create one for you in the highest scope (global). Check my answer here on how implied globals work for a more detailed example, or read the MDN pages, especially the section on Name conflicts
Lastly, I'd like to add that globals, especially implied globals, are evil. Also know that the ECMA6 standard is clearly moving away from global variables and introduces support for true block-scopes. As you can see here
Oh, and if you want to check if a function uses implied globals: 'use strict'; is a great thing:
(function()
{
'use strict';
var localVar = 123;//ok
impliedGlobal = 123;//TypeError!
}());
As you can see, implied globals are not allowed. See MDN on strict mode for the full explanation
The second form, with global i might actually be a bit slower because it's defined in a higher scope, and variables defined in a higher scope take longer to resolve.
Aside from any performance considerations just stick with common guidelines unless performance is really an issue. In this case: scope your variables as narrowly as possible.
I would strongly advise you to use the first form.
The first way you did it is fine. Each instance of i would have no knowledge of the other i in the other functions.
You should read this tutorial on global versus local variables
Also, could I suggest an optimization. Why can't you just do the following to cover any number (instead of separate functions for each number)?
var elements = [];
function addNumbah(number){
elements.push(number);
}
It is okay to declare variables with same name in different functions.
Variables declared inside a function only exist in the scope of that function, so having the same variable name across different functions will not break anything.
In fact, it is good form to keep variables in as small of a scope as possible! Global variables can be difficult to manage and can create really bad bugs, especially if one function isn't done using the variable when another function tries to access it.
Specifically for simple variables, declaring
var i = 0;
every time is perfectly fine.
You can declare a variable multiple times..In your code you are declaring Variable i in different scopes here:
//Here you are declaring variable i local to addNumbah1,2 functions
var elements = [];
function addNumbah1(){
var i = 1;
elements.push(i);
}
function addNumbah2(){
var i = 2;
elements.push(i);
}
//Here v /variable i has been declared globally
var elements = [];
var i
function addNumbah1(){
i = 1;
elements.push(i);
}
function addNumbah2(){
i = 2;
elements.push(i);
}
Note that although you can declare a variable multiple times but generally its not a good programming practice as it may cause bugs/problems in your application

Where do I have to declare variables when making a loop for in javascript?

I see two differents way for declaring variables when making a "for loop" in javascript:
First way:
for (var i = 0, l = [].length; i < l; i += 1) {
// make something
}
Second way:
var i;
var l;
for (i = 0, l = [].length; i < l; i += 1) {
// make something
}
Is there some reason to prefer one of these?
They are same, you can use either BUT first is more readable and terse.
The point is that variables in both cases are local with the presence of var keyword. With first method also, you create two local variables:
var i, l
Instead of
var i
var l
Why use var keyword again and again when only one can do it. In fact that turns out to be one of the good practices of JS.
Given the code you show, they are the same thing. However, JS has some oddities which could cause issues in more complex code. Also, there is a question of maintainability and readability for future devs. Some of it is very subjective, some of it is objective.
I use a combination of the two, with slight variation--single var statement, top of scope.
var x = function () {
var i,
l;
for (i = 0, l = [].length; i < l; i += 1) {
// make something
}
};
The reason being that I prefer a single var statement per scope (function), and that statement to be at the top of the scope. JSLint/JSHint enforce this by default. Objectively, it helps avoid issues with the JS hoisting mechanism, which moves all variable declarations to the top of scope during the pre-execution pass. Admittedly subjectively, it makes very clear to later developers which variables are introduced in this scope. Any other var in use in the scope is assumed to be coming from a higher-level scope.
In javascript there is no difference except from a maintainability point of view. keeping declarations and usage close by helps in better readability. You should choose which ever is more readable.
No, both those are correct. I prefer the first myself.
An incorrect way is:
for (var i = l = 0; ...; ...) {
...
}
Where there is no comma between i and l wich causes l to be global.
No, at least in Chrome the scope is exactly the same and both ways are equivalent.
actually according to the almighty crockford there is: because javascript has function scope it is preferred to always declare variables first thing in the head of the function.
However, as others have pointed out, it doesnt really matter and should be done according to personal taste and readability.
The reason why one would prefer the second over the first is that variables in JS don't have block scope, but instead lexical (or function) scope, which means that variable are visible within the function they are defined (they are also visible in nested functions).
Example:
function foo() {
for (var i = 0; i < 10; i++) {
alert(i);
}
alert(i); // works, because i has lexical scope
}
In most C-like languages, variables have block scope, which means they are visible within the block where they are defined, so:
void foo() {
for (int i = 0; i < 10; i++) {
print(i);
}
}
print(i); // won't work, i is not visible any more
So, people coming from languages like Java/C/C++ may think that var i in the first example has block scope, where it actually has not. This is why some programmers prefer declaring all variables at the beginning of functions.
Personally I think even then you should stick to the habit to declare variables as close as possible to where they are used.
EDIT
As JAAulde mentioned, you should only declare variables close to their usage if you've really understood JS scoping rules (and quirks).

Categories

Resources