简体   繁体   中英

Declaring a Javascript variable twice in same scope - Is it an issue?

Would the following code cause any issues?:

var a = 1;
var a = 2;

My understanding is that javascript variables are declared at the start of the scope. For example:

var foo = 'a';
foo = 'b';
var bar = 'c';

Is processed as:

var foo;
var bar;
foo = 'a';
foo = 'b';
bar = 'c';

Therefore would my initial code snippet become:

var a;
a = 1;
a = 2;

Or would it become:

var a;
var a;
a = 1;
a = 2;

I understand that declaring a javascript variable twice in the same scope isn't good practice, but I'm more interested in the impact of doing this.

As you said, by twice of more the same var, JavaScript moves that declaration to the top of the scope and then your code would become like this:

var a;
a = 1;
a = 2;

Therefore, it doesn't give us any error.

This same behaviour occurs to for loops (they doesn't have a local scope in their headers), so the code below is really common:

for (var i = 0; i < n; i++) {
    // ...
}
for (var i = 0; i < m; i++) {
    // ...
}

That's why JavaScript gurus like Douglas Crockford suggest programmers to manually move those declarations to the top of the scope:

var i;    // declare here
for (i = 0; i < n; i++) {    // initialize here...
    // ...
}
for (i = 0; i < m; i++) {    // ... and here
    // ...
}

Declaring the same variable twice is as good as declaring it once. Below statement will not bring any impact.

var a, a;

in the below case you are just overriding the variable foo. This will have an impact if you have foo defined in the local and global scope. JS will search foo in the local scope first and then if it doesn't find it will look in the global scope.

var foo;
var bar;
foo = 'a';
foo = 'b';
bar = 'c';

Let's try to transcript what ECMAScript® 2021 Language Specification says.

First, according to JavaScript: Understanding the Weird Parts there are two phases of running code: Creation Phase and Execution Phase . Conceptually it's like code is processed twice (not executed, processed).

For var a = 5; statement this is happening:

  • Creation Phase : memory allocation for identifier a and undefined value set to this memory (so called hoisting )
  • Execution Phase : put value 5 into memory associated with identifier a (instead of undefined )

Now 14.3.2 Variable Statement section of ECMAScript® 2021 Language Specification says this

A var statement declares variables that are scoped to the running execution context's VariableEnvironment . Var variables are created when their containing Environment Record is instantiated and are initialized to undefined when created. Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration but those declarations collectively define only one variable. A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer's AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.

Let's examine it line by line.

Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration

In this case BindingIdentifier is just a identifier. Statement means these syntaxes are allowed officially .

var a;
var a;
var a = 1;
var a = 2;
var a, a;
var a = 1, a = 2;

but those declarations collectively define only one variable

Directly says it's the same variable , only one memory is allocated.

Conceptually you might think that if at Creation Phase variable with identifier ( a is our case) was already created , it's creation is skipped (previous statement already allocated memory and set undefined into it).

A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer's AssignmentExpression when the VariableDeclaration is executed, not when the variable is created

Just further emphasizes difference between assignment (happens at Execution Phase ) and variable creation (happens at Creation Phase ) of this statement

var a = 5;

Explanation

Now let's summarize what we know. This syntax is officially supported by specification. It means only one variable is created (one memory location to hold value)

var a = 1;
var a = 2;

It has nothing to do with hoisting . Hoisting is still happening as usual.

console.log(a) // this is undefined
var a = 1;
var a = 2;

Assignments will happen at Execution Phase line by line, changing value at the same memory location .

console.log(a) // undefined
var a = 1;
console.log(a) // 1
var a = 2;
console.log(a) // 2

Such a duplicate variable declaration will not cause any problems thanks to javascript's variable hoisting feature. so in your DOM wherever you have declared variables but assigned (or) not assigned, they will be placed at the top during compilation.

Example:
    var foo='hai!';
    bar='welcome!';
    var bar;

You may expect above code snippet should throw "unidentified" error but still javascript manages it by placing the bar variable's declaration at the top. So even before variable declaration its value can be assigned as opposed to other languages.

Hope this helps you to some extent

If you initialize the same variable twice, there will be no error on the console but if you are working on some application (like guess my number) and want to reset all the elements to the initial state. All the elements will be set to the initial state but the variable that was initialized twice will stick to its modified value only. Example, If the initial score is 20 and then modified to say some number 15, now reset button is pressed in order to set the value to initial but it will not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM