为什么对象没有看到他的方法?

时间:2012-01-06 14:49:20

标签: javascript html5-canvas

我正在使用框架atomJS和库libCanvas开发游戏。以下是发生错误的代码:

var Planet=atom.Class({
//other code
clearLayer : function (layer) {
        layer.ctx.clearRect(this.x, this.y, this.size, this.size);
    },
colonize : function (layer, angle, color,ms) {
        **this.clearLayer(layer);**
        drawArc({
            context: layer.ctx,
            x: Math.round(this.x + this.size / 2),
            y: Math.round(this.y + this.size / 2),
            radius: this.radius + 5,
            width: 4,
            color: color,
            opacity: 0.6,
            angleFinish: angle
        });
        if (this.colonizing) {
            //if (this.cursorOnPlanet()) this.context.fillText(COLONIZING, (this.x + this.size / 2) - 30, this.y + this.size - 2);
            this.colonizingTimer = setTimeout(this.colonize, ms,layer, angle + 5, color,ms);
            if (angle > 360) {
                this.colonizing = false;
                this.state = 1;
            }
        } else {
            clearTimeout(this.colonizingTimer);
            this.clearLayer(layer);
        }
    },
});

在这一行,this.clearLayer(layer);脚本终止时出现错误Object [object DOMWindow] has no method 'clearLayer'。请告诉我,问题是什么? 谢谢!

4 个答案:

答案 0 :(得分:0)

了解whateverObject.colonize()实际上是如何被调用的很重要。无论如何,很明显原始对象的方法在被调用之前被绑定到不同的对象。这在事件处理程序中相当常见,例如,this通常(但不总是)最终成为事件目标,而不是方法的原始对象。

开发人员通常使用闭包来确保它们具有原始this的安全引用。例如,您可以在构造函数中定义colonize var self=this;,这样可以保证名称self指向原始this,即使this本身也是如此反弹。

另一种方法是使用Function.prototype.bind(你必须为旧JS引擎填充),它创建一个新的函数,this对象保证是你指定的任何东西。

答案 1 :(得分:0)

听起来这个函数是从DOM窗口而不是本地类调用的。当this对象是一个窗口时,您将不可避免地遇到范围问题。

您的问题在于setTimeout功能。当调用超时时,它会告诉DOMWindow而不是本地类来调用该函数。要解决此问题,请将调用包装到函数中。 function(){<code>}

编辑:我不太确定setTimeout中额外字段的用途,所以我省略了我的解决方案。如果你在函数中包装你正在做的任何事情,它应该可以工作。

答案 2 :(得分:0)

变化

this.colonizingTimer = setTimeout(this.colonize, ms,layer, angle + 5, color,ms);

var self = this;
this.colonizingTimer = setTimeout(function(){self.colonize.call(self);}, ms,layer, angle + 5, color,ms);

问题在于,由于超时,this对象将从对象范围中删除,并且在执行时引用没有名为{{1}的方法的全局对象(window) }。

这是一个simplified demo来看看差异。

答案 3 :(得分:0)

&安培;最正确的方法是使用&#34;延迟&#34;:

this.colonizingTimer = this.colonize.delay(ms, this, [layer, angle + 5, color, ms]);

但是,如果我理解你想要将角度从零度调整到360度?为什么不使用&#34; Animatable&#34; &安培; &#34; .animate&#34; ?

关于LibCanvas的每一个问题,您都可以发送电子邮件至shocksilien@gmail.com