开发者问题收集

对象构造函数中的递归函数和 TypeError

2017-01-25
1036

鉴于以下 <img id="f1" src="img/fish1.gif"> ,我创建了一个对象构造函数,如下所示(为了演示目的, 缩小了 代码):

$(function(){
  function fish(i){

    this.f = $('#f'+i)[0];
    this.d = '-=1px';

    this.animateFish = function(){
      $(this.f).animate({"left": this.d} ,10, "linear", this.checkCollision);
    }

    this.checkCollision = function(){
      this.animateFish();   //TypeError: this.animateFish is not a function
    }
  }

  var f1 = new fish(1);
  f1.animateFish();
})

我应该为 img 制作动画(在本例中为 #f1),检查碰撞,然后调用 this.animate ,这会引发上述错误,有什么解决办法吗?

3个回答

animate() 的回调函数中, this 将引用正在动画化的元素,而不是 fish 对象。因此,调用 this.animateFish() 会给出函数未找到错误。

要解决此问题,请将对 fish 对象的引用存储在事件处理程序范围内的变量中,然后您可以在事件处理程序中使用该变量。尝试此操作:

function fish(i) {
  var _this = this;
  _this.$f = $('#f' + i);
  _this.d = '-=1px';

  _this.animateFish = function() {
    _this.$f.animate({ "left": _this.d }, 10, "linear", _this.checkCollision);
  }

  _this.checkCollision = function() {
    _this.animateFish();
  }
}
Rory McCrossan
2017-01-25

每次声明新的 function () { 时,其中的任何 this 都将引用函数中新创建的上下文。在构造函数中,您有

this.animateFish = function(){
  $(this.f).animate({"left": this.d} ,10, "linear", this.checkCollision);
}

因此,函数内部的 this.fthis.dthis.checkCollision 引用您正在构造的对象上的属性,而是引用该函数创建的新 this 上下文。

正如 Rory McCrossan 的回答所说,您可以 创建一个新变量, var _this = this (尽管我更喜欢 var self = this ,但这只是我的风格)。然而,在 ES6 中,您现在可以使用 箭头函数 ,这些函数没有自己的 this 上下文。

function fish(i){
  this.f = $('#f'+i)[0];
  this.d = '-=1px';

  this.animateFish = () => {
    $(this.f).animate({"left": this.d} ,10, "linear", this.checkCollision);
  }

  this.checkCollision = () => {
    this.animateFish();
  }
}

当您声明一个新的 () => {}code> 函数时,其中的任何 this 都将“继承”,即引用声明该函数的相同 this 上下文。因此,在上面的代码中, this.fthis.dthis.checkCollisionthis.animateFish 引用新构造对象的属性,这正是您想要的。

chharvey
2018-12-30

最好不要在构造函数内定义对象的方法,而是在原型上定义对象的方法。如果您在构造函数中定义方法,则每次构建 new Fish() 时,它将获得自己的这些方法的副本。取而代之的是,您可以通过将方法分配给原型来节省空间,以便所有鱼类实例都可以共享相同的方法。

有两种方法可以做到这一点。一个人正在使用旧的ES5技术,实际上是访问原型。

165050696

可以同时修复您的代码中的错误,因为 this < /代码>在每个原型函数中确实是指鱼实例。为了使您充分了解此代码的工作原理,您需要对 原型链 ,这就是为什么我推荐下面的技术 - '只是工作'。

第二种技术是使用ES6类,如果您可以支持。

501593197

这也将修复您的错误,因为每个方法内的 将参考鱼类实例。

chharvey
2018-12-30