0

I am trying to pass "dynamic" (data is changed frequently by keypress event) body and direction.

I am calling function to like this:

snakeGame.createInterval(snakeGame.move, grid, body, direction, interval);



  createInterval: function(f, grid, body, direction, interval) {
    setInterval(function() { f(grid, body, direction); }, interval);
  },

Problem is that both body and direction always keep same data when function was called.

Let's say that direction was 'right' when calling it first time and before second occurence happens, direction was changed to 'up', but this function still reads it as old 'right'.

How do I make sure that passed parameters are always up-to-date?

(Let me know if you need further clarification)

  • Possible duplicate of [How can I pass a parameter to a setTimeout() callback?](https://stackoverflow.com/questions/1190642/how-can-i-pass-a-parameter-to-a-settimeout-callback) – Patrick Barr Jul 07 '17 at 17:37
  • see [this answer](https://stackoverflow.com/a/7503942/1985574) in specific – Patrick Barr Jul 07 '17 at 17:37
  • Also note: the variables are "dynamic", but they're [enclosed](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). – Patrick Barr Jul 07 '17 at 17:38

1 Answers1

1

To see changes to values, you need references to those values, and make sure that both the code that changes values and the code that read the values use a reference to the same value.

There are several ways to do this, but it will involve an object with several object properties which will have the targetted values. But you will pass the object, not the individual values.

From the little you have provided, it looks like you have a snakeGame object. You could use that object to store some of the properties, for instance, it could have a property grid. But you could also introduce another object, for storing things you'd rather not have in your snakeGame object. This could be the case for body and/or direction.

For instance:

// Use object properties instead of separate variables: 
var snake = {
    body: 'xxxx',
    direction: 'L'
}

var snakeGame = {
    // You can also add properties to your existing object:
    grid: [[0,0,0],[0,0,0],[0,0,0]],
    createInterval: function(f, snake, interval) {
        // Pass `this` and snake objects:
        setInterval(f.bind(this, snake), interval); 
    },
    move: function(snake) {
        // use this.grid, snake.body and snake.direction: 
        //....
    }
    // etc
};

// Call with objects only (except for the constant interval)
snakeGame.createInterval(snakeGame.move, snake, interval);

// When you change direction:
$('#up').keydown(function () {
    // ... do not assign to snake, but to snake.direction:
    snake.direction = 'U';
    // ...
    // Same principle with snake.body.
});

I just chose to define grid as a property of snakeGame, and direction and body as properties of a newly introduced object. But you may want to do it differently. This is just an example. The essence is that you pass along objects, not primitive values, but that you assign to properties of those objects, never redefining the objects themselves.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • Creating an object and calling it inside made the trick. Thank you. –  Jul 10 '17 at 07:24
  • Fantastic. How would I then clearInterval from within createInterval(). Just need help on a slightly similar implementation... – GONeale Apr 05 '19 at 03:29
  • 1
    @GONeale, `clearInterval` will work like in any other case. If you have a particular problem in making it work, then could you please ask a new question? NB: there is a little button for when you think an answer is fantastic ;-) – trincot Apr 05 '19 at 05:13