0

您好,这是我第一次尝试编写 JavaScript 应用程序,所以我是使用它编写 OOP 代码的新手。

以下代码在控制台中运行,没有任何错误:

// Main file for the application
$(document).ready( function()
{
    var app = new application;
    setInterval( app.run, 50 );

});

function application()
{
   var canvas = Raphael(10,0,400,400);
   this.molecule = new molecule( new Vec2(50,50),new Vec2(1,0),canvas );
   this.molecule.update(10);

   this.run = function()
    {

    }
}

但是,这段代码不起作用:

// Main file for the application
$(document).ready( function()
{
    var app = new application;
    setInterval( app.run, 50 );

});

function application()
{
   var canvas = Raphael(10,0,400,400);
   this.molecule = new molecule( new Vec2(50,50),new Vec2(1,0),canvas );

   this.run = function()
    {
        this.molecule.update(10);
    }
}

它在控制台中给出以下错误:

Uncaught TypeError: Object function molecule( pos,vel,canvas )
    {
        this.radius = 5;
        this.color = "red";

        this.canvas = canvas;

        this.pos = pos;
        this.vel = vel;

        this.circle = canvas.circle( this.pos.x,this.pos.y,this.radius );

        this.circle.attr("fill", this.color );


    } has no method 'update' 

这是包含分子对象的源文件。

    // This 'class' handles a molecule, including movement and drawing.

    function molecule( pos,vel,canvas )
    {
        this.radius = 5;
        this.color = "red";

        this.canvas = canvas;

        this.pos = pos;
        this.vel = vel;

        this.circle = canvas.circle( this.pos.x,this.pos.y,this.radius );

        this.circle.attr("fill", this.color );


    }

 // Updates the molecule
    molecule.prototype.update = function( deltaTime )
    {
        this.pos += this.vel * deltaTime;
        this.setPosition(this.pos);
    }

    // Accepts a Vec2
    molecule.prototype.setPosition = function( pos )
    {
        this.circle.translate( pos.x-this.pos.x, pos.y-this.pos.y );
    }    

对于我发布的大量代码,我感到很抱歉,但我很困惑为什么第一段代码有效,而第二段代码无效。有人可以为我解释一下吗?非常感谢。

4

2 回答 2

1

一个常见的错误,它需要对 JavaScript 有很好的理解才能看到这里发生了什么。问题是这一行:

setInterval( app.run, 50 );

这会导致在没有适当上下文app.run的情况下间隔用完时被调用。为确保将其作为其上下文调用,您需要以下内容:thisrunappthis

setInterval( function() {
    app.run();
}, 50 );

或使用最新的 JavaScript(仅在非常现代的浏览器中):

setInterval( app.run.bind(app), 50 );

JavaScript 中函数的this上下文取决于函数的调用方式。基本上,它由调用它的对象决定。例如,在 中app.run(),该run方法被调用app并且它将按预期工作。但是,在稍微不同的情况下

var fn = app.run;
fn();

该函数在没有对象上调用,因此this不会被设置,导致意外结果。这正是您的情况。解决方案是确保传递一个可以在任何对象上调用的函数,并run在正确的对象上调用该函数。

于 2013-02-16T20:38:21.013 回答
0

您已将run方法与app. 传递一个将它们保持在一起的函数。

setTimeout(function() { app.run(); }, 50);

现在thisin的值.run()将成为app对象。


此外,没有必要为每个对象创建一个新run方法。application()你可以装runapplication.prototype

function application() {
   var canvas = Raphael(10,0,400,400);
   this.molecule = new molecule( new Vec2(50,50),new Vec2(1,0),canvas );
   this.molecule.update(10);
}

application.prototype.run =  function() {
    this.molecule.update(10);
}

尽管如果您确实保留run在构造函数中,那么您可以将其关闭在引用该对象的变量上,因此您可以安全地分离它。

function application() {
   var canvas = Raphael(10,0,400,400);
   this.molecule = new molecule( new Vec2(50,50),new Vec2(1,0),canvas );
   this.molecule.update(10);

   var self = this;

   this.run = function() {
       self.molecule.update(10);
   }
}

setTimeout(app.run, 50)
于 2013-02-16T20:37:53.153 回答