You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何setInterval无法调用自定义对象方法?附动画代码问题

问题分析与修复方案

咱们一步步拆解你代码里的问题,解决这个「fn is not a function」报错和动画静止的问题:

1. 直接触发报错的核心问题:传了函数执行结果而非函数本身

你调用 runOnInterval(tesla.moveRight(), 10) 时加了括号 (),这会立即执行moveRight方法,并把它的返回值(这里moveRight没有return,所以是undefined)传给runOnInterval的fn参数。当setInterval里尝试调用fn(arg)时,fn是undefined,自然会抛出「fn is not a function」的错误。

修复方式:去掉括号,传递函数引用即可:

runOnInterval(tesla.moveRight, 10);

2. moveRight与draw方法的逻辑漏洞

  • 首先,moveRight里的this.x;是完全无效的代码,你需要更新实例的x坐标,应该改成this.x += distance;,这样每次调用才会累加位置,实现持续移动的效果。
  • 其次,你直接把distance赋值给left,而不是更新后的this.x,这样每次都会把车定位到10px的位置,自然看不到移动。另外,draw方法里只创建了carHtml字符串,但没有把元素挂载到DOM,也没赋值给this.carElement,导致moveRight里调用this.carElement.css()时会报错。

修复draw和moveRight方法:

Car.prototype.draw = function() {
  var carHtml = '<img src="http://nostarch.com/images/car.png">';
  // 创建DOM元素并添加到页面
  this.carElement = $(carHtml);
  $('body').append(this.carElement);
  // 初始化车辆位置
  this.carElement.css({ left: this.x, top: this.y });
};

Car.prototype.moveRight = function(distance) {
  // 更新x轴坐标
  this.x += distance;
  // 应用新的位置
  this.carElement.css({ left: this.x, top: this.y });
};

3. 容易忽略的this指向丢失问题

即使你传了tesla.moveRight给runOnInterval,在setInterval的回调里调用fn(arg)时,moveRight里的this会指向window(而非tesla实例),导致this.x和this.carElement无法正确访问。

解决方式:两种常用方案任选其一:

  • 方案一:传参时用bind绑定实例:
runOnInterval(tesla.moveRight.bind(tesla), 10);
  • 方案二:修改runOnInterval,支持传入上下文:
function runOnInterval(fn, arg, context) {
  setInterval(function () {
    fn.call(context, arg);
  }, 1000);
}
// 调用时传入tesla作为上下文
runOnInterval(tesla.moveRight, 10, tesla);

完整修复后的代码示例

var Car = function(x, y) {
  this.x = x;
  this.y = y;
};

Car.prototype.draw = function() {
  var carHtml = '<img src="http://nostarch.com/images/car.png">';
  this.carElement = $(carHtml);
  $('body').append(this.carElement);
  this.carElement.css({ left: this.x, top: this.y });
};

Car.prototype.moveRight = function(distance) {
  this.x += distance;
  this.carElement.css({ left: this.x, top: this.y });
};

var tesla = new Car(20, 20);
tesla.draw();

function runOnInterval(fn, arg, context) {
  setInterval(function () {
    fn.call(context, arg);
  }, 1000);
}

runOnInterval(tesla.moveRight, 10, tesla);

内容的提问来源于stack exchange,提问作者Michael Alexander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:34:51