1

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)).

3
  • Be specific about your question inital post asks for ..**The second function alerts "undefined" instead of "one".** ..late in your update you ask for ** WHY ** ?this causes confusion on the anwsers which we provide. Commented Jul 18, 2012 at 18:57
  • 1
    Sorry, but in the first post i wrote And if I comment block bellow, alerts "one" correctly. Someone knows why?....so, I think that I asked why. Commented Jul 18, 2012 at 19:00
  • Fine have just read it at first I went through with your provided JSFiddle.. Commented Jul 18, 2012 at 19:02

4 Answers 4

5

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);
}
Sign up to request clarification or add additional context in comments.

Comments

2

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"​

http://jsfiddle.net/mKdhx/

1 Comment

Why is the previous definition unset even when the execution never reaches the var myParam = "two"; line?
2

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.

Comments

-1

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

2 Comments

I didn't downvote, but they're in two different functions -- JS has function scope, not block scope. Also, it doesn't actually have to be in global scope, it could exist in a non-global shared scope, like a function that wraps all the code.
agreed about global scope. about block scope - yes I meant function scope - just didn't say correctly

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.