I want to make a simple game, learning HTML, CSS and javaScript. I wrote code in which I want a function to go to the next one by clicking a button. Its has a flow like the code below. It does not work as I intend. I want it to return to the first function when a round finished. But from the second round buttons start to call next funcitons several times by one click. What do I misunderstand? I show the console output at the bottom.
<body>
<button id="toFunc2">toFunc2</button>
<button id="toFunc3">toFunc3</button>
<button id ="toFunc4">toFunc4</button>
<button id ="toFunc1">toFunc1</button>
<p></p>
</body>
<script>
window.addEventListener("DOMContentLoaded", function(){
function functionFour(obj) {
obj.nowFunctionFour += 1;
console.log(`nowFunctionFour: ${ obj.nowFunctionFour }`);
obj.toFunc1Button.addEventListener("click", function(){
functionOne(obj);
})
}
function functionThree(obj) {
obj.nowFunctionThree += 1;
console.log(`nowFunctionThree: ${ obj.nowFunctionThree }`);
obj.toFunc4Button.addEventListener("click", function(){
functionFour(obj);
});
}
function functionTwo(obj) {
obj.nowFunctionTwo += 1;
console.log(`nowFunctionTwo: ${ obj.nowFunctionTwo }`);
obj.toFunc3Button.addEventListener("click", function(){
functionThree(obj);
});
}
function functionOne(obj) {
obj.nowFunctionOne += 1;
console.log(`nowFunctionOne: ${ obj.nowFunctionOne }`);
obj.toFunc2Button.addEventListener("click", function(){
functionTwo(obj);
})
}
const obj = {
toFunc2Button: document.getElementById("toFunc2"),
toFunc3Button: document.getElementById("toFunc3"),
toFunc4Button: document.getElementById("toFunc4"),
toFunc1Button: document.getElementById("toFunc1"),
nowFunctionOne: 0,
nowFunctionTwo: 0,
nowFunctionThree: 0,
nowFunctionFour: 0
}
functionOne(obj);
})
</script>
-------Console Output------- nowFunctionOne: 1 nowFunctionTwo: 1 nowFunctionThree: 1 nowFunctionFour: 1 nowFunctionOne: 2 nowFunctionTwo: 2 nowFunctionTwo: 3
The way the event listeners work in JavaScript is that:
You can attach multiple event listeners to the same DOM element
Because of this, you can accidentally attach the same listener twice or more times to the same element. That way, for each event you will see that the event listener is being invoked multiple times although they are actually different listeners with the same code! This is what has happened with your implementation
.
On your first round, when
functionOne
is invoked, an event listener gets attached. On your second round,functionOne
is invoked again & by executing the code line by line another event listener gets attached (with same code) to the element. Hence you get the issue!
I would propose you attach the event handlers separately & for one time only.
<html>
<body>
<button id="toFunc2">toFunc2</button>
<button id="toFunc3">toFunc3</button>
<button id="toFunc4">toFunc4</button>
<button id="toFunc1">toFunc1</button>
<p></p>
<script>
window.addEventListener("DOMContentLoaded", function () {
const obj = {
nowFunctionOne: 0,
nowFunctionTwo: 0,
nowFunctionThree: 0,
nowFunctionFour: 0,
};
function functionFour() {
obj.nowFunctionFour += 1;
console.log(`nowFunctionFour: ${obj.nowFunctionFour}`);
}
function functionThree() {
obj.nowFunctionThree += 1;
console.log(`nowFunctionThree: ${obj.nowFunctionThree}`);
}
function functionTwo() {
obj.nowFunctionTwo += 1;
console.log(`nowFunctionTwo: ${obj.nowFunctionTwo}`);
}
function functionOne() {
obj.nowFunctionOne += 1;
console.log(`nowFunctionOne: ${obj.nowFunctionOne}`);
}
const attachEventListeners = () => {
document.getElementById("toFunc1").addEventListener("click", functionOne);
document.getElementById("toFunc2").addEventListener("click", functionTwo);
document.getElementById("toFunc3").addEventListener("click", functionThree);
document.getElementById("toFunc4").addEventListener("click", functionFour);
};
attachEventListeners();
})
</script>
</body>
</html>