1

So I am trying to get familiar with classes and methods but I just cant understand why certain thing work the way they are. I was trying to make a rectangle and just move it along axis-X whit the click on the window.

const canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
const goBtn = document.getElementById('go');

class Snake{
    constructor(positionX, positionY){
        this.positionX = positionX;
        this.positionY = positionY;
    }
    draw(){
        ctx.fillStyle = "#FF0000";
        ctx.fillRect(this.positionX, this.positionY, 25, 25);
    }
    move(){
        ctx.clearRect(this.positionX, this.positionY, canvas.width, canvas.height);
        this.positionX +=25;
        ctx.fillRect(this.positionX, this.positionY, 25, 25);
        console.log("something");
    }
}
let player = new Snake(250,250);
player.draw();
goBtn.addEventListener('click', player.move());

In this first cenario the player.draw() works fine but the player.move() runs automatically, and the event listener is not working.

window.addEventListener('click', player.move);

In the second scenario I removed the brackets from player.move. This time the event listener is working but only the consol.log('something'), the rest of the method is not.

move = () => {...
window.addEventListener('click', player.move());

After this I changed the funtion to an arrow function and but back the brackets to player.move() Here it works like on the first try it work one time atomatically witouth the evetn listener working.

Finally I removed the brackets once again...

move = () => {...
window.addEventListener('click', player.move);

And it worked just perfectly.

Can someone explain why these things are happening, or just send me some sites that explain this? Thanks in advance.

Here an executable version of my version 1 of my implementation:

const canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
const goBtn = document.getElementById('go');

class Snake{
    constructor(positionX, positionY){
        this.positionX = positionX;
        this.positionY = positionY;
    }
    draw(){
        ctx.fillStyle = "#FF0000";
        ctx.fillRect(this.positionX, this.positionY, 25, 25);
    }
    move(){
        ctx.clearRect(this.positionX, this.positionY, canvas.width, canvas.height);
        this.positionX += 25;
        ctx.fillRect(this.positionX, this.positionY, 25, 25);
        console.log("something");
    }
}
// changed player position to it is visible in snippet
let player = new Snake(50,50);
player.draw();
goBtn.addEventListener('click', player.move());
<button id="go">Go</button>
<canvas width="400" height="100" id="canvas"></canvas>
Mushroomator
  • 6,516
  • 1
  • 10
  • 27
kiriboi
  • 11
  • 1
  • 1
    `()` after a function or method reference means that the function should be called **immediately**. The syntax of the language does not include a special case for when a function reference is being passed to another function; `()` always calls the function. – Pointy May 07 '22 at 12:18
  • okay thank you but this still doesnt explain the secong scenarion where only the the console.log works and not the rest of the method. Or am I missing something? – kiriboi May 07 '22 at 12:27
  • 1
    That has to do with how [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) works in JavaScript. You could use `window.addEventListener('click', () => player.move());` or use `bind()` to get the expected behavior like this `goBtn.addEventListener('click', player.move.bind(player));`. – Mushroomator May 07 '22 at 12:40
  • Like Pointy says, the ()'s execute the method. Think of functions like they're vars. you're just telling which function to execute when the event happens. So you're passing a reference to the function (like you're pointing at the function)... kinda like how you pas vars around. Functions are "first class citizens". See: https://www.javascripttutorial.net/javascript-functions-are-first-class-citizens/ – bob May 08 '22 at 00:42

0 Answers0