简体   繁体   中英

Undeclared variables in an ..if statement doesn't throw an error

I have just noticed some curious behaviour in Javascript. In my quest to write short code, I came up with the function below:

if(a = 'A|B|C'.split('|'), a.length > 1){
  // I have access to a, but it was never declared as a variable?
} else {
  // some code
}

// I still have access to 'a' over here?

I expected the code to throw some error about a not being declared, but apparently, it assigns the value of 'A|B|C'.split('|') to it, and using a comma, I can use a as a normal declared variable.

Further more, the variable exists outside of the if statement, and I have access to it in the code that follows below.

Another thing, explicitly setting the variable:

if(let a = 'A|B|C'.split('|'), a.length > 1)

Throws an error. This is different from the for, for ..in loop, which you have to declare the variables before using them.

Can someone explain how that is valid?

In fact a is declared as a global variable when you just assign the value to it. It will declared systematically as part of the global window object.

If you take a look at the MDN var reference you can see that:

Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed.

So that's why the code you shared is working perfectly, and doesn't throw any error.

Normally, JS doesn't throws error on the variables which are undeclared but values are assigned to them.

Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed.

If you like to get these kind of errors then add your script in the strict mode by using "use strict"; line at the top of your function.

"use strict"; Defines that JavaScript code should be executed in "strict mode". With strict mode, you can not, for example, use undeclared variables.

This is your provided code which is not throwing error:

 if(a = 'A|B|C'.split('|'), a.length > 1){ // I have access to a, but it was never declared as a variable? } else { // some code } console.log(a); 

This is the code in which i have just add the strict directive at the top and it starts throwing an error.

 "use strict"; if(a = 'A|B|C'.split('|'), a.length > 1){ // I have access to a, but it was never declared as a variable? } else { // some code } 

There are multiple things going on here. Will try to explain each of them.

Firstly, in the below line you have multiple expressions separated by a comma. In JS each expression is evaluated from left to right and the last expression is returned. So basically this will work as follows

if(a = 'A|B|C'.split('|'), a.length > 1){ // evaluate 'A|B|C'.split('|') and assign the value to a variable 'a' if it exists. Otherwise create a new global variable 'a' and assign the value.

will convert into

if(a,a.length > 1) // a gets assigned a value which 
// here is an array consisting of 3 elements.["A","B","C"].

will convert into

if(["A","B","C"], ["A","B","C"].length > 1)

will convert into

if(true) // comma separated expression always 
// returns the last expression's value which here would be true since a.length is 3

Hence you would always get the if block code run.

The second issue you mentioned is because you cannot write statements inside and if block. and using var/let is basically a statement. Remember you can write expressions inside if condition.

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