对象构造函数中的递归函数和 TypeError
鉴于以下
<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
,这会引发上述错误,有什么解决办法吗?
在
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();
}
}
每次声明新的
function () {
时,其中的任何
this
都将引用函数中新创建的上下文。在构造函数中,您有
this.animateFish = function(){
$(this.f).animate({"left": this.d} ,10, "linear", this.checkCollision);
}
因此,函数内部的
this.f
、
this.d
和
this.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.f
、
this.d
、
this.checkCollision
和
this.animateFish
引用新构造对象的属性,这正是您想要的。
最好不要在构造函数内定义对象的方法,而是在原型上定义对象的方法。如果您在构造函数中定义方法,则每次构建
new Fish()
时,它将获得自己的这些方法的副本。取而代之的是,您可以通过将方法分配给原型来节省空间,以便所有鱼类实例都可以共享相同的方法。
有两种方法可以做到这一点。一个人正在使用旧的ES5技术,实际上是访问原型。
165050696
可以同时修复您的代码中的错误,因为
此
this < /代码>在每个原型函数中确实是指鱼实例。为了使您充分了解此代码的工作原理,您需要对
原型链
,这就是为什么我推荐下面的技术 - '只是工作'。
第二种技术是使用ES6类,如果您可以支持。
501593197
这也将修复您的错误,因为每个方法内的 将参考鱼类实例。