Say I\'m trying to execute this JavaScript snippet. Assume the undeclared vars and methods are declared elsewhere, above, and that something
and something
Javascript has function scope. That means that magicvar
will exist from the beginning of the function it's declared in all the way to the end of that function, even if that statement doesn't ever execute. This is called variable hoisting. The same thing happens with functions declarations, which in turn is called function hoisting.
If the variable is declared in global scope, it will be visible to everything. This is part of the reason why global variables are considered evil in Javascript.
Your example will pass undefined
into magicFunction
if something
is false, because magicVar
hasn't been assigned to anything.
While this is technically valid Javascript, it's generally considered bad style and will not pass style checkers like jsLint. Extremely unintuitive Javascript like this will execute without any error
alert(a); //alerts "undefined"
var a;
POP QUIZ: What does the following code do?
(function() {
x = 2;
var x;
alert(x);
})();
alert(x);
I agree with variable hoisting and function hoisting, I would like to emphasis two import points.
Identifier Defined in Catch parameter is i.e. err/e(error) , is scoped to Catch defined block.
Function first hoisting. example :
b(); // output : 3
var b = 2;
function b(){
return 3;
}
Due to javascript "hoisting" (google it), your variable declaration code gets translated as:
function yourFunction() {
var magicVar;
try {
if(something) {
magicVar = -1;
}
if(somethingElse) {
magicFunction(magicVar);
}
} catch(e) {
doSomethingWithError(e);
}
} //end of your function
"Hoisting" moves all variables declarations to the top of the function. So magicVar
is available everywhere in the function, but it's undefined until you give it a value.
Your variable has function scope.
Lots of other good answers about how Javascript handles this with var
, but I thought I'd address the let
situation...
If a variable is defined with let
inside the try
block, it will NOT be in scope inside the catch
(or finally
) block(s). It would need to be defined in the enclosing block.
For example, in the following code block, the console output will be "Outside":
let xyz = "Outside";
try {
let xyz = "Inside";
throw new Error("Blah");
} catch (err) {
console.log(xyz);
}
With var
, variables exist from the beginning of the function to the end of it, no matter where they are declared, or even if the statement is actually ever reached. They will, however, be undefined
until they are assigned another value.
So in your case, if something
is false but somethingelse
is true, you will call magicFunction
with its first argument being undefined
.
The let
keyword, created in Javascript 1.9 and available (as of today, May 3rd 2012, and as far as I know) only in Firefox, declares variables with the scoped semantics you're probably used to.
var
You may want to read MDN scope cheat sheet
Due to hoisting
You can even do things like this:
function bar() {
var x = "outer";
function foo() {
alert(x); // {undefined} Doesn't refer to the outerscope x
// Due the the var hoising next:
x = 'inner';
var x;
alert(x); // inner
}
foo();
}
bar();
bar();
Demo
So the foo
function is converted to something like this:
function foo() {
var x;
alert(x); // {undefined} Doesn't refer to the outerscope x
// Due the the var hoising next:
x = 'inner';
alert(x); // inner
}
My question is: what is the scope of magicVar and is it okay to pass it into magicFunction as I've done?
Define okay..., Yes the code is valid, but it's less readable then if the variables declarations were on the top, that's all.