views:

713

answers:

4

I've been using JSLint to make me feel bad about my JavaScript. It is great, by the way. There is one check that I don't quite understand and I'd like your views, please.

From jslint.com: In languages with block scope, it is usually recommended that variables be declared at the site of first use. But because JavaScript does not have block scope, it is wiser to declare all of a function's variables at the top of the function. It is recommended that a single var statement be used per function.

What is the last sentance in bold really saying? I think I should be declaring multiple variables like this?

var foo = 1, bar = 2;

And, is the "wise" part just a programming style to discourage errors down the line or is there more to it than that?

Thanks for your help.

+2  A: 

Basically in JavaScript blocks ({ ... }) do not introduce a new scope, there is only function-scope, so no scope is created on any other statement.

A variable introduced anywhere in a function is visible everywhere in the function.

For example:

function myFunction(){
  var one = 1;

  if (one){
    var two = one + 1;
  }

  (function () {
    var three = one + two;
  })();

  // at this point both variables *one* and *two* are accessible but 
  // the variable *three* was declared in the scope of a inner function
  // and is not accessible  at this point.
}

In languages with block scope, it recommended to declare the variables at the point of first use, but since JavaScript does not have block scope, it is better to declare all of a function's variables at the top of the function.

Check this article.

CMS
You don't really explain why it's better though. It does eventually follow from function only scope that it's better for vars to be at the top. But you've left out the reasoning steps from that fact, to your conclusion.
Breton
I've just read the article you linked to, and it makes the same mistake as Chetan. redeclaring a var is a NOOP. It is completely benign and doesn't cause any problems. THat's not to say that restricting yourself to one var statement is useless, but you, nor the article, has actually made a convincing case for it.
Breton
@Breton, it can cause problems because it's often a reflection of a confused programmer. It can also confuse other programmers who do the sensible thing and put all the vars are the top of the function.
Nosredna
If this is the reasoning, then that should be in the original answer. As it stands it's like a syllogism that's missing its second premise.
Breton
Kittens are furry and small. Therefore Kittens are cute. (As true as it is, it's an invalid argument, because you've left out "all Furry and small things are cute")
Breton
+2  A: 

Yes, it means that you declare all variables at the beginning of the function. Whether you want to do it in one line or multiple lines is a matter of choice.

The reason is explained in the paragraph you mentioned. Javascript variables only have function level scope. If you declare the same variable inside an if/while/for block, it will be overwritten by the new value since the block doesn't carry a new scope. This is different from languages such as Java. To avoid such surprises, declare all the variables you are going to use in the function at the beginning of function so that you don't accidentally 'redeclare' andything.

Chetan Sastry
I don't think redeclaring a variable is the problem. That doesn't throw an error like it does in C (or java?). In fact it does nothing.
Breton
Sorry, I must have been more clear. What I meant was declaring the same variable name inside a block, which is allowed in Java. This new variable lives only inside the block.
Chetan Sastry
Ah yes, I suppose that would be a problem if you were used to a language with block scope.
Breton
My reading comprehension skills are shit today. I totally misunderstood your original post.
Breton
No problem, I could have framed my answer better too.
Chetan Sastry
+15  A: 

The problem is that, whether you realise it or not, javascript invisibly moves all the var declarations to the top of the function scope.

so if you have a function like this

var i = 5
function testvar () {
     alert(i);
     var i=3;
}
testvar();

the alert window will contain undefined. because internally, it's been changed into this:

var i = 5
function testvar () {
     var i;
     alert(i);
     i=3;
}
testvar();

this is called "hoisting". The reason crockford so strongly advocates var declarations go at the top, is that it makes the code visibly match what it's going to do, instead of allowing invisible and unexpected behavior to occur.

Breton
Interesting - never really knew that about JS - of course, I usually define all my variables at the top anyway, and rarely reuse a variable name from an outer loop/function.
gnarf
This is interesting, but not really related to block scope.
Triptych
But it is a valid answer to my question...
objektivs
This doesn't answer the part of the question highlighted in bold, namely, why only one var statement is recommended. This only explains the rationale for why var statement(s) should appear at the beginning of a function. Any idea's for why only one is recommended? I am curious because to my eyes that negatively impacts the code's readability.
Michael Lang
@Michael-Lang well I couldn't tell you how other people rationalize it, but for my part it forces me to use as few variables as possible, which is good code style. If a function starts to have so many variables that you need multiple var statements to keep it clear, I'd say that's a code smell (and I'm guilty!). Having a single var statement, next to the parameters also gives you all the elements at play in a function in a single place at a single glance. Having each on a seperate line can be less clear, and takes up space a minifier can't compress, and you can stick things inbetween.
Breton
@Michael-Lang .. here's a bit more insight from Crockford: "R. D. Tennent wrote a book called 'The Principles of Programming Languages' in which he demonstrated the Principle of Correspondence, which was a correspondence between variables and parameters. JavaScript demonstrates it really well. This shows that you could imagine a subset of JavaScript which didn't have variables — would that still be a useful language? It turns out yes, and this is the proof that anything you can write with variables you can write without variables. You can use a function closure instead to do the same thing."
Breton
+1  A: 

The lack of block scope explains the code below:

var a = 1;
if (something) {
    var a = 2;
}

alert(a); // Alerts "2"

In most C-style (as in syntax) languages, the var a = 2 definition would define 'a' only for the scope of the if block. Using a single var statement at the top of the function helps to avoid this quirk of Javascript, which is not always as obvious as the above, and would be unexpected to C/C#/Java programmers.

Triptych