Reputation: 12389
I found a bug in my site, because of this strange behavior. The second function alerts "undefined" instead of "one".
function test() {
var myParam = "one"
if (false) {
var myParam = "two";
}
alert(myParam);
}
test(); // alert "one"
function testAjax() {
var myParam = "one";
$.ajax({
url: "http://url-to-get-error",
error: function(){
if (false) {
var myParam = "two";
}
alert(myParam);
}
});
}
testAjax(); // alert "undefined"
And if I comment block bellow, alerts "one" correctly. Someone knows why?
if (false) {
var myParam = "two";
}
See in http://jsfiddle.net/EaW8D/2/.
UPDATE
Guys, I know how to to solve the problem, thanks a lot!
But the question is WHY js is setting undefined in a block
that NEVER run (if (false)
).
Upvotes: 1
Views: 426
Reputation: 115950
All variable declarations of the form var myParam
are hoisted to the top of the function scope. Even if they are in inaccessible blocks or at the end of the function, a function with a var
declaration in it anywhere will treat all instance of that variable name as local.
Consider this handler:
error: function(){
alert(myParam);
var myParam;
}
It will also cause a undefined
alert, because the var myParam
at the bottom means, "Treat all instance of myParam
that come both before and after this declaration as local variables in this function." The same hoisting that applies in this case applies in your inaccessible-logic-block case.
Upvotes: 2
Reputation: 816442
Someone knows why?
You are re-declaring myParam
inside the error handler, shadowing the variable with the same name in the outer scope. Variable declarations are "hoisted" to the top of the function, so your code is effectively the same as:
error: function(){
var myParam; // <- declaration
if (false) {
myParam = "two"; // <- initialization
}
alert(myParam);
}
and since the if
block is never executed, myParam
will be undefined
(the default value for uninitialized variables).
Here is a simple example to proof this behaviour. If the variable was not hoisted, foo
would become a global variable (assuming non-strict mode) and a property of window
, but it does not:
(function() {
if(false) {
var foo = 'bar';
}
foo = 'baz';
console.log(window.foo); // yields `undefined`
}());
To solve this problem, simply remove var
, so that myParam
refers to the variable declared in the outer scope, testAjax
:
error: function(){
if (false) {
myParam = "two";
}
alert(myParam);
}
Upvotes: 5
Reputation: 50493
Because you're creating myParam
as a new
var
again
function testAjax() {
var myParam = "one";
$.ajax({
url: "http://url-to-get-error",
error: function(){
if (false) {
myParam = "two";
}
alert(myParam);
}
});
}
testAjax(); // alert "undefined"
Upvotes: 2
Reputation: 1985
in second situation your myParam=one and myParam=two are in different blocks - and moreover callback of ajax error is not "under" testAjax in terms of variable visibility - it's asynchroneus. You would need myParam in global scope
Upvotes: -1