Scylla Scylla - 3 months ago 17
Javascript Question

Javascript closure (this)

I have already looked everywhere on stackoverflow, but couldn't find any answer for this.

Uncaught TypeError: this.rsGame is not a function (same about this.addEnemy)

let game = new Phaser.Game(600,600);
let speed = 500;


let scyla = {

preload: () => {
game.load.image('bg', 'assets/bg.png');
game.load.image('pl', 'assets/pl.png');
game.load.image('enemy', 'assets/enemy.png');

},
create: () => {

game.physics.startSystem(Phaser.Physics.ARCADE)

game.add.sprite(0,0, 'bg');

this.player = game.add.sprite(300, 500, 'pl');
this.player.anchor.set(0.5);

game.physics.arcade.enable(this.player);
this.cursors = game.input.keyboard.createCursorKeys();

this.enemies = game.add.group();

// this.timer = game.time.events.loop(200, this.addEnemy(), this);
},
update: () => {

this.player.body.velocity.x = 0;
this.player.body.velocity.y = 0;

if (this.cursors.left.isDown)
this.player.body.velocity.x = speed * -1;

if (this.cursors.right.isDown)
this.player.body.velocity.x = speed;

if (this.cursors.up.isDown)
this.player.body.velocity.y = speed * -1;

if (this.cursors.down.isDown)
this.player.body.velocity.y = speed;

if (this.player.inWorld === false)
this.rsGame();
},
rsGame: () => {
game.state.start('scyla');

},
addEnemy: () => {
let enemy = game.add.sprite(300, 100, 'enemy');
game.physics.arcade.enable(enemy);
enemy.body.gravity.y = 200;

this.enemies.add(enemy);
enemy.checkWorldBounds = true;
enemy.outOfBoundsKill = true;
}
}

game.state.add('scyla', scyla);
game.state.start('scyla');


I tried things like

let self = this


this return the windows object anyway. This has something to do with closure, but I don't understand exactly

don't know how to solve this :/

Answer

Arrow function set this to the lexical scope. You're trying to access the scyla object but the arrow function is setting it to window (or whatever this is equal to at the time that you declare scyla).

Either reference scyla directly:

scyla.rsGame();

or write your methods using standard function expressions:

update: function() {
    ...
    if (this.player.inWorld === false)
        this.rsGame(); 
}

or shorthand method declarations:

update() {
    ...
    if (this.player.inWorld === false)
        this.rsGame();
}