bboybeatle bboybeatle - 7 months ago 11
Javascript Question

Function not picking up changed variable, is it not global?

So I have a pretty simple quiz made up of 7 select boxes and a submit button. What I'm trying to achieve is to make a warning error pop up if none of the select boxes have been changed, and if they have been changed for it to bring up the score.

I've set up a variable called 'changed' which is false. When one of those select boxes is changed 'changed' becomes true...

This works and I have a console log which shows me its working, however when the submit button is pressed, which calls the function to show the scores or the warning it doesn't seem to recognise that 'changed' has changed to TRUE.

Heres the Jquery...

var changed = false;

$('select').on('change', function () {

var changed = true;
console.log('TRUE');

});

$("#button").click( function(){

var correct = 0;

var selectValue;

var questions = document.getElementsByClassName("question");

var numOfQuestions = questions.length;

for(var i = 0; i < questions.length; i++ ){//begin for loop

//get the value of the select element
selectValue = questions[i].options[questions[i].selectedIndex].value;

//if the value equals right
if(selectValue === "right"){//begin if then

//increment the correct variable
correct++;

}//end if then

}//end for loop



if(changed === false){
$('#scoreDisplay span').append('WARNING');
}
else{

$('#scoreDisplay span').append(correct);

}
});


you can see it in action here, but you will see it just shows 'WARNING' when you click submit, regardless of whether you've changed any select boxes... http://gogeye.com/connectquiz/index.html

Answer

The redefinition of var changed in this event handler:

$('select').on('change', function () {

    // creates a new local variable that is only available inside this function
    var changed = true;
    console.log('TRUE');

});

makes a new local variable that "shadows" and "hides" the changed variable declared in a higher scope.

Remove the var from the one inside your function so it is not creating a new variable of that name, but is instead just setting the higher scoped one:

var changed = false;

$('select').on('change', function () {

    // no var in front of this variable so you are just setting
    // the earlier one, not creating a new one
    changed = true;
    console.log('TRUE');

});

Remember, anytime you declare a variable with var inside a function, it defines a new local variable that is only available within that function. If that happens to have the same name as a variable in a higher scope, then it overrides that variable name and the interpreter uses the local one instead of the higher scoped one anytime you reference it.

The Javascript interpret does a scope search to resolve a variable reference. First it looks in the local scope. If it is found there, then it uses the one it found there. If it is not found there, it then looks at the next higher scope. If not found there, it goes up to a higher scope until it gets up to the global scope. So, the closest scope it finds the variable name in is the one that is used - thus a var or let defined local variable will be used first.