Как я могу передать аргумент с requestAnimationFrame?

В основной программе я случайным образом выбираю объект, который хотел бы анимировать, поэтому я вызываю функцию с объектом в качестве аргумента. Первый цикл в порядке, x точно установлен, но на следующем ходу он становится undefined.

Что-то вроде этого:

var anim = {
        mainFunc: function(x) {
            anim.update(x);
            anim.redraw(x);
            window.requestAnimationFrame(anim.mainFunc);
        },

        update: function(x) {

        },

        redraw: function(x) {

        }
};

var n=Math.floor(Math.random() * (ArrayOfAnimObject.length));
anim.mainFunc(ArrayOfAnimObject[n]);

Ответ 1

Вам нужно либо создать ссылку, либо обернуть вызов функции в другую функцию следующим образом:

mainFunc: function(x) {
    anim.update(x);
    anim.redraw(x);
    window.requestAnimationFrame(function() {
        anim.mainFunc(x);
    });
}

Ответ 2

Вы также можете использовать .bind.

mainFunc: function(x) {
    anim.update(x);
    anim.redraw(x);
    window.requestAnimationFrame(anim.mainFunc.bind(anim,x));
}

Ответ 3

Лучше всего избегать этого.

Решения, которые позволят вам сделать это, потребуют, чтобы вы создавали новую функцию (будь то анонимная оболочка из ответа @kalley или связанная из @ArchyWillHe's) каждый кадр.

В цикле анимации вы хотите оставить как можно меньше собираемых объектов, чтобы сборщик мусора не включался во время работы анимации, убивая несколько кадров, когда это произойдет.

Для этого у вас есть разные стратегии, но, например, в случае, представленном в OP, этот параметр x вероятно, должен быть напрямую связан с объектом anim:

var anim = {
  mainFunc: function() {
    anim.update();
    anim.redraw();
    window.requestAnimationFrame(this.mainFunc);
  },

  update: function() {
    this.x ++;
  },

  redraw: function() {
    log.textContent = this.x;
  }
};
// replace it with a bound function only once
anim.mainFunc = anim.mainFunc.bind(anim);
anim.x = 0; // attach the parameter to the anim object
anim.mainFunc();
<pre id="log"></pre>