Hivekeeper Hivekeeper - 2 months ago 9
jQuery Question

Cannot alter jQuery object variable. Is this a scope issue?

I have a simple script to move a sprite around the screen with the arrow keys. I want to contain a reference to my $('#sprite') in a variable called $s. But depending on where I declare and initialize $s, I get either a working function or a non working function. Why is this?

Edit: The difference is where I declare and initialize $s. I accidentally put the same code snippet in twice, but that's fixed now.

This does not work:



$(document).ready(main());



function main(){

var $s = $("#sprite");
var time = 'fast';


$(document).keydown(function(e){
// var $s = $("#sprite");
console.log($s);
key = e.which
switch(key){
case 37: //left
$s.animate({left: "-=10px"}, time);
console.log("left");
break;
case 38: //up
$s.animate({top: "-=10px"}, time)
console.log("up");
break;
case 39: //right
$s.animate({left: "+=10px"}, time)
console.log("right");
break;
case 40: //down
$s.animate({top: "+=10px"}, time)
console.log("down");
break;
default:
break;
}

});

};





This works:



$(document).ready(main());



function main(){

// var $s = $("#sprite");
var time = 'fast';

$(document).keydown(function(e){
var $s = $("#sprite");
console.log($s);
key = e.which
switch(key){
case 37: //left
$s.animate({left: "-=10px"}, time);
console.log("left");
break;
case 38: //up
$s.animate({top: "-=10px"}, time)
console.log("up");
break;
case 39: //right
$s.animate({left: "+=10px"}, time)
console.log("right");
break;
case 40: //down
$s.animate({top: "+=10px"}, time)
console.log("down");
break;
default:
break;
}

});

};




Answer

The difference is whether you declare $s inside the keydown handler or outside? Let's look at what's happening, from the start:

$(document).ready(main());

You are CALLING the function main, and passing its return value to $(document).ready(). This is not what you want to do. Here, main gets executed immediately. What you want is:

$(document).ready(main);

without parentheses, just passing a reference to the function.

Why does it matter?

When you call the function immediately, the DOM isn't ready yet, and then $s has no value if it is defined in the outer function. But when you set it in the inner function, $s doesn't get set until you press a key, and by then the element exists.

So really, either one should work. The problem is in that other line of code.