28

In the main program I randomly choose an object which I'd like to animate, so I call the function with the object as the argument. The first loop is okay, x is finely set, but in the next turn it becomes undefined.

Something like this:

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]);
4

3 回答 3

44

您需要创建一个引用或将函数调用包装在另一个函数中,如下所示:

mainFunc: function(x) {
    anim.update(x);
    anim.redraw(x);
    window.requestAnimationFrame(function() {
        anim.mainFunc(x);
    });
}
于 2013-11-10T18:29:27.667 回答
24

您也可以使用.bind.

mainFunc: function(x) {
    anim.update(x);
    anim.redraw(x);
    window.requestAnimationFrame(anim.mainFunc.bind(anim,x));
}
于 2015-11-08T08:09:20.700 回答
6

最好的办法可能是避免不得不这样做。

允许您执行此操作的解决方案将要求您每帧创建一个新函数(无论是来自@kalley 答案的匿名包装器,还是来自@ArchyWillHe 的绑定包装器)。

在动画循环中,您希望尽可能保留不太可收集的对象,这样垃圾收集器就不必在动画运行时启动,在它发生时杀死几帧。

为了执行此操作,您可以使用不同的策略,但例如在 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>

人们也可能更喜欢将此参数保留为可供调用者和 的变量anim

(function() {

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

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

  redraw: function() {
    log.textContent = x;
  }
};
var x = 0; // available for both us and anim's method
anim.mainFunc();

})();
<pre id="log"></pre>

于 2019-04-25T01:58:15.113 回答