I'm writing simple rock-paper-scissors game. In this piece of code I'm trying to assign id value of the clicked img to a variable using .forEach method. It just doesn't work. If statements does work but somehow string doesn't add to a variable.
const weapons = document.querySelectorAll("img");
let playerWeapon = "";
weapons.forEach((weapon) => {
weapon.addEventListener("click", (event) => {
if (weapon.id == "paper") {
playerWeapon += "paper";
} else if (weapon.id == "scissors") {
playerWeapon += "scissors";
} else if (weapon.id == "rock") {
playerWeapon += "rock";
}
});
});
console.log(playerWeapon);
I've replaced concatenation with console.log to see if it returns value and it does return them. Tried adding return before concatenation, didn't help.
You are facing the difference between synchronous
and asynchronous
code.
Javascript usually executes the code synchronously, which means the JS interpreter executes immediately one line at a time from top to bottom.
But you are using a callback function
as well, which will be executed asynchron(at a later time) - when a user clicks on a weapon
.
Lets have a closer look into your code:
weapons.forEach((weapon) => {
// this line of code gets executed synchronously
weapon.addEventListener("click", (event) => {
// this is your callback function
// this block scope executes asynchron
if (weapon.id == "paper") {
playerWeapon += "paper";
} else if (weapon.id == "scissors") {
playerWeapon += "scissors";
} else if (weapon.id == "rock") {
playerWeapon += "rock";
}
// asynchronous code end
});
});
The second argument of addEventlistener
is a callback function. A callback function is a javascript function, which is passed as parameter into another function. You have to be aware that this function is just defined but not executed yet!
This function will be executed internally.
So when you run your code, than your console.log(playerWeapon)
will be executed before the code in your callback function. Thats the reason for getting just an empty string in your console output.
What you can do instead of use console.log
is adding an HTML Element which shows your clicked weapon or just use console.log
e.g
// add an html element to your page for showing your selected weapon
const weaponHTML = document.getElementById('selected-weapon');
const weapons = document.querySelectorAll("img");
weapons.forEach((weapon) => {
weapon.addEventListener("click", (event) => {
// every time you click a weapon the id of the img element will be set as text into your new selected-weapon element
weaponHTML.innerText = weapon.id
// or you can do this instead
console.log(weapon.id)
});
});