There is no reason why you can’t do this. The simple answer to your question “Does this mean the event handler is registered and ready to accept events as long as the program is running once the function is called?” is yes.
If the 9 squares in the game are represented by buttons and given the ids b11, b12, etc. then what you have done is added an event handler to each button without duplicating the code 9 times. The event handler is straight forward in that it sets the button to be an x or an o. This is a clever way to avoid all the repeated code, but there is a better way. But first, let me answer your second question “WHY DOES THIS WORK”.
The way it works is called a closure. The function checkIfTaken
is a function and as such has its own environment in which choice
is declared and assigned a value of “b11”, or “b12”, etc. When the statement onEvent
is called it creates an unnamed function in that environment. That function uses the variable choice
whose value is the id of one of the 9 buttons. That unnamed function then becomes the callback function for the button with id equal to the value of choice. When clicked that function is called.
The closure part is that since the callback function was defined inside an environment where choice
was declared and given a value equal to the button’s id it will continue to have that value. setProperty(choice, "image","icon://fa-times");
will set the image property of the button that is pressed because the callback function uses the environment created for checkIfTaken
and in that environment choice
is set to the button id that is the button whose callback this function is. This is an advanced Javascript topic not covered by CSP.
This is also not covered in CS A because Java doesn’t have closures. Javascript is based on the language Scheme which is based on the language LISP which does have closures.
So how could you do this without creating closures? Use the button id from the event object. The callback function is given an object as a parameter. That object is called an event and has all kinds of information including the id of the button that was pressed. You just need to understand that onEvent
needs a function for the callback and you don’t have to create a fresh function every time. Hence:
var player = "O";
onEvent("b11", "click", squareChosen);
onEvent("b12", "click", squareChosen);
onEvent("b13", "click", squareChosen);
onEvent("b21", "click", squareChosen);
onEvent("b22", "click", squareChosen);
onEvent("b23", "click", squareChosen);
onEvent("b31", "click", squareChosen);
onEvent("b32", "click", squareChosen);
onEvent("b33", "click", squareChosen);
function squareChosen(event){
var choice = event.currentTargetId;
console.log(choice + " is clicked!");
if(player == "X")
setProperty(choice, "image","icon://fa-times");
else
setProperty(choice, "image","icon://fa-circle-thin");
checkWin(player);
}
will also work without duplicating the callback function code 9 times.