Using an event parameter to a callback function along with event.target

I’m re-doing a simple Rock, Paper, Scissors game this time adding an UI with DOM methods. I have a function getComputerChoice() that works and returns a lowercase string with one of the three options randomly.

I have another function PlayRound(computerChoice, userChoice) that takes both strings returned and does some comparisons over them.

function playRound(computerChoice, userChoice) {


        if (userChoice === computerChoice) {
            console.log("----------------");
            console.log("Draw!");
            console.log("User choice was: " + userChoice);
            console.log("Computer choice was: " + computerChoice);
            console.log("----------------");

inally I have a getUserChoice() function that I’m updating. It used to look like:

        function getUserChoice() {
        let userChoice = prompt("What is your weapon? ");
        return userChoice.toLowerCase();
    }

And the program worked with that.

Now, instead of a prompt the user can click one of three buttons. I changed the button so that I get the id of each button which matches one of either three choices

//USER CHOICE METHOD
function getUserChoice() {
    const userChoice = document.querySelectorAll('button');

    userChoice.forEach((choice) => {
        choice.addEventListener('click', () => {
            console.log(choice.id);

        })
    })
}

The thing is that with this function “as-is” the playRound()'s userChoice is undefined, and in:

       function getUserChoice() {
        const userChoice = document.querySelectorAll('button');

        userChoice.forEach((choice) => {
            choice.addEventListener('click', () => {
                console.log("this: " + this.id);
                console.log(choice.id);

            })
        })
    }

this is undefined.

My question is, how do I make getUserChoice (using the .forEach and eventListener) return a valid argument (string) that can be used by 'playRound()`?

I’ve been told that this isn’t passed into arrow functions and that I should use an event parameter to a callback function along with event.target. I don’t understand how. I’ve also been told that I shouldn’t use a callback function, or at least playRound() as a callback function given that:

 You are passing whatever playRound() returned to the addEventListener to call. That doesn't work since playRound() function does not return a function``

Hi @bardifacundo,

Welcome to the forum :slight_smile:

A late one for me, so maybe a bit sketchy. Just a quick observation.

Arrow functions don’t have their own ‘this’ property. With arrow functions ‘this’ is lexically scoped. Looking at your code, I would assume ‘this’ is coming from getUserChoice.

If you were to change your code to a standard function, you should get what you expect e.g.

choice.addEventListener('click', function() {
  console.log("this: " + this.id);
  console.log(choice.id);
})

Alternatively you could use event.target

choice.addEventListener('click', (event) => {
  const target = event.target
  console.log("this: " + target.id);
  console.log(choice.id);
})

Edit: Just read the last bit of your post. I agree.

I’ve been told that this isn’t passed into arrow functions and that I should use an event parameter to a callback function along with event.target . I don’t understand how. I’ve also been told that I shouldn’t use a callback function, or at least playRound() as a callback function given that:

One of the best reasons for event handlers to use the information from the event object, is that it helps to reinforce the idea that event handlers should be restricted only to handling the event.

The job of the event handler is to obtain information from the event, and pass that information off to some other function for processing.

In this case, that would mean obtaining a reference to the button, and passing that button to some other function for processing, such as to getUserChoice()

function getUserChoice(button) {
  return button.id;
}
choice.addEventListener('click', (event) => {
  const button = event.target;
  const computerWeapon = getComputerChoice();
  const userWeapon = getUserChoice(button);
  console.log(userWeapon);
  playRound(computerWeapon, userWeapon);
});

Something like that. Even so, I’d be tempted to push getComputerChoice() into the playRound() function, or to a playUserChoice() function, as the event handler has no impact on that computer choice.

function getUserChoice(button) {
  return button.id;
}
function playUserChoice(userWeapon) {
  const computerWeapon = getComputerChoice();
  playRound(computerWeapon, userWeapon);
}
choice.addEventListener('click', (event) => {
  const button = event.target;
  const userWeapon = getUserChoice(button);
  console.log(userWeapon);
  playUserChoice(userWeapon);
});

Thanks! it worked. I have to read more about EventListener and how they work.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.