Douglas Crockford has changed the way that multiple variables are defined.
Previously, a comma-separated list was considered to be the correct way to define multiple variables:
var foo = "Foo",
bar = "Bar";
// Invalid - results in the following error: Expected ';' and instead saw ','.
JsLint.com now considers the above to be incorrect.
It can still accept the comma-separated list though when you use the multivar declaration:
/*jslint multivar */
var foo = "Foo",
bar = "Bar";
The recent change to how JSLint.com handles variables, now requires that each variable is to be defined separately.
I suspect that this is to make refactoring your code easier to achieve.
For anybody that wants a way to automatically convert from the list format to an each-line format, Pretty Diff has a varword setting that can help you to automatically convert from one way to another.
presumably this will now both fail jslint AND cannot be automatically converted.
I still think this way of doing the declaration is cleaner than either of the other two alternatives so I guess Iâll be specifying multivar whenever I use jslint in future (or simply ignoring that stupid incorrect error).
It can be automatically corrected, but it does result in some silly looking code:
var foo;
var bar;
foo = "Foo";
bar = "Bar";
When refactoring your code with the above, such as to move the bar variable down in to a separate function, more work is needed to shift things around than if the following were done instead:
[quote=âfelgall, post:4, topic:221408, full:trueâ]
I donât want it corrected. I think the way I code it more accurately reflects how JavaScript works and that both of the alternatives are misleading.[/quote]
I felt that way too when it came to assembly language. Itâs a tricky balance to maintain, representing what is actually happening versus ability to work with the code.
In the interest of learning more, what potential problems do you foresee occurring when variables are declared at the top of their scope when using this syntax?
As long as people realise that the declarations all happen before the first assignment there shouldnât be any problems.
There is minimal code there preceding the apparent declaration of bar. The further the difference between the actual declaration of bar and its apparent definition, the more possibility of code in between malfunctioning because of code that assumes bar is not yet declared.
For less skilled people, isnât that something that code linters will easily catch?
I foresee a problem with declaring the variables separately at the top.
The following code will be considered by a linter to be correct, because the variable is already declared:
var foo, bar;
foo = "Foo";
doSomething(bar);
bar = "Bar";
whereas, the following code will result in linters catching the error, because the linter can catch the intent of the undeclared variable being used, even though JavaScript still has it declared as being undefined.
var foo = "Foo";
doSomething(bar);
var bar = "Bar";
And yes, declaring a variable later on is another code smell that it easily found too.
That is perfectly valid code - bar does already exist at that point - only its value is undefined.
There is a very real difference between a field that is undeclared and one that is declared but has not yet had a value assigned. Thatâs why the only one var at the top concept was introduced in the first place.
There are some areas of JavaScript where it can make a significant difference to the processing whether a field is declared but has not yet had a value assigned to it or whether it has had a value assigned.so understanding the difference between the two is important.
Anyway,
var foo = "Foo";
var bar = "Bar";
does not take into account where the value to be assigned to bar involves calculations.
For example if the value of bar is dependent on an if statement.
if (x > 0) bar = "positiive";
else bar = 'Not Positive";
where does the var go in that code? (Letâs assume x is a parameter passed into the current function so that it can have any value without it affecting the declaration and assignment of foo).
The if statement was a simple example - for more complex alternatives only the - create another function that will only ever be run form this one spot - will work. Thatâs one extra function for every variable used by this function just in order that the variable has one first assignment to attach the var to.
Also no matter which way you write it doesnât change the fact that bar is being declared before any values are assigned so my version more accurately reflects the order in which the code executes for the rare case where it actually makes a difference.
Consider the following:
function doSomething(x) {
var myArray;
myArray = [x];
myArray.forEach(function(a) {console.log(a);}) ;
}
var foo = "Foo";
doSomething(bar);
var bar = "Bar";
given that the var statement for bar comes after the doSomething call a person not realising that bar gets declared before the foo assignment might expect that the forEach statement shouldnât output anything as there are no declared entries in the array whereas in fact bar has been declared and so that method would output a value for it. With my version of the code it is more obvious that bar is declared at the time of running the function. Also even if the var declaring bar does come after the doSomething(bar) the error is that the declare isnât above the use of bar in that call - the error isnât that the call is being done before a value is assigned to bar - the function might expect to be called both before and after values are assigned.
So how would you modify:
var foo = "Foo";
doSomething(bar);
var bar = "Bar";
so that the var bar occurs prior to the doSomething() without changing the value that my doSomething() function outputs?
Currently the code relies on what is called a side-effect, where a declared variable is undefined until itâs actually declared.
I would declare bar as being undefined, then assign a value to it later. This helps to inform anyone reading the code clearly about my intention, so that possible thoughts about whether I intended it or not are less likely to occur.
var foo = "Foo";
var bar = undefined;
// do stuff with undefined bar
...
bar = "Bar";
That statement is just nonsense and is indicative of the mistake people keep making regarding where variables are declared in JavaScript - ALWAYS BEFORE THE FIRST STATEMENT EXECUTES. In your code bar is still being actually declared before the assignment to foo regardless of where in the code the var bar appears.
Perhaps you meant âa variable doesnât exist at all until it is declared and a declared variable is considered to have a value of undefined until such time as an assignment statement assigns a different value to it.â
I think this demonstrates the problem you asked me about earlier. Having multiple var statements misleads people into incorrect thinking as with your incorrect statement regarding where bar is actually declared. If you (who know JavaScript really well) can make such incorrect statements regarding where the variables are actually declared then what chance do we have of teaching people where the declarations really happen unless we write the code to match?
That statement is just nonsense and is indicative of the mistake people keep making regarding where variables are declared in JavaScript - ALWAYS BEFORE THE FIRST STATEMENT EXECUTES. In your code bar is still being actually declared before the assignment to foo regardless of where in the code the var bar appears.[/quote]
The bar variable is undefined before the first statement executes. I mean what I said - a declared variable is undefined until itâs actually declared.
I will be charitable and believe that you misunderstood me to say âis undeclared until itâs actually declaredâ which is definitely wrong.
The following code should help to clear this up:
var foo = "Foo";
log.innerHTML += "Foo and Bar before bar is declared.<br>";
log.innerHTML += "Foo " + foo + "<br>";
log.innerHTML += "Bar " + bar + "<br>";
var bar = "Bar";
log.innerHTML += "Foo and Bar after bar is declared.<br>";
log.innerHTML += "Foo " + foo + "<br>";
log.innerHTML += "Bar " + bar + "<br>";
Results in:
Foo and Bar before bar is declared.
Foo: Foo
Bar: undefined
Foo and Bar after bar is declared.
Foo: Foo
Bar: Bar
Because, a declared variable is undefined until itâs actually declared.
both foo and bar are ACTUALLY declared before the value is assigned to foo.
Your statement is incorrect because before they are actually declared (as opposed to where the declaration appears in the code) they donât exist.
The variables have a value of undefined between where they are actually declared (at the top of the code) and where a value is first assigned to replace it - regardless of whether this assignment appears before or after the apparent declaration in the code.
All variables declared in a function are ACTUALLY declared before any of the statements in that function are run - regardless of where the apparent declaration appears in the code.
We both agree that between the start of a block of code, and the place that âvar barâ is written, that the variable still exists from the beginning of that block as an undefined variable.
The rest seems to be a misunderstanding of what âdeclared variableâ means. For me, it means the place where the coder writes âvar bar = âŚâ with the understanding that the variable is undefined between the start of the block of code and that place where the you declare the defined variable.
If I am wrong I would love to be directed to suitable reference material to clear up the matter.
For what itâs worth, Iâve been declaring my variables at their point of first use for a long time, and I rely on linters to catch hoisting mistakes.
var x = 42;
function f() {
console.log(x);
var x;
}
JsLint will report ââxâ is out of scopeâ, and JsHint will report ââxâ was used before it was definedâ.
I agree. The former â though technically valid â is almost certainly a mistake and wonât be caught by a linter.
I agree.[quote=âPaul_Wilkins, post:5, topic:221408â]
In the interest of learning more, what potential problems do you foresee occurring when variables are declared at the top of their scope when using this syntax?
[/quote]
The problems I foresee occurring is a misunderstanding of what âdeclared variableâ means. Not much of a prediction since it has always been the case where the order of the code doesnât match the exact execution order.
Where in the code the actual declaration is shown the declaration is hoist to the top of the function. The scope of the variables is the entire function and not just from where the declaration appears in the code.
When using âuse strictâ any variable not declared generates a syntax error before any of the code in the function is run as thatâs the point at which the declarations are run.
[quote=âfelgall, post:17, topic:221408, full:trueâ]
The problems I foresee occurring is a misunderstanding of what âdeclared variableâ means.[/quote]
Please clarify what I have misunderstood about a declared variable?
As a reminder - I have never said that a variable exists only from where the âvar barâ is written, I have said that a variable is undefined up until that point. And I have always said that variables should be declared at the top of their scope.
If I havenât misunderstood anything, then we both seem to be in agreement as to how JavaScript interprets the code.
The reference to âactually declaredâ is misleading - variables are declared at the top of their scope regardless of where the declaration appears.
So âactually declaredâ can be interpreted two different ways - as being the actual spot where the declarations are run (as I interpret it to mean) or as the spot in the code where the var reference just happens to be (as you interpret it to mean).
Since the declarations are done before anything else regardless of where they appear even the following code will work:
if (x > 0) bar = "positive";
else var bar = 'Not Positive";
Note that I am not suggesting that this is a good way to write the code, just pointing out that bar is declared before anything is assigned to it even if it were to be coded like this.
I think the important thing is that people learn that regardless of where the declaration appears in the code that it will actually be run before any of the actual statements in the code are run.
If a particular arrangement is going to be detected as an error by linters then the linter is assuming that the person doesnât fully understand how declaring variables actually works.
[quote=âfelgall, post:19, topic:221408, full:trueâ]
The reference to âactually declaredâ is misleading - variables are declared at the top of their scope regardless of where the declaration appears.[/quote]
By that reasoning, it seems that MDN var is also misleading with itâs copious use of âvariable declarationsâ and âdeclared variablesâ to refer to the line of code that âvar barâ has been written.
I donât agree with that line of reasoning.
Even the ECMAScript 2015 standards paper that nobody reads (section 13.3.2 on page 196) says 'declares variables" in terms of the âvar barâ line of code.
Perhaps you need a different word? Initialize is one that the specs uses, that more clearly conveys the desired intent.