2013-02-16 45 views
0

您好,這是我第一次嘗試編寫JavaScript應用程序,所以我不熟悉使用它編寫OOP代碼。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); 
    }  

我對大量的我已經張貼代碼抱歉,但我難倒,爲什麼代碼的第一件工作,而第二個則不會。任何人都可以幫我解釋一下嗎?非常感謝。

回答

1

一個常見的錯誤,它需要JavaScript的一個很好的理解,看看這裏發生了什麼。問題是這樣的線:

setInterval(app.run, 50); 

這導致app.run當間隔用完沒有適當this上下文被調用。爲了確保run被稱爲與appthis情況下,你需要的東西,如:

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

或與最新的JavaScript(僅在非常現代的瀏覽器):

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

的的this上下文JavaScript中的函數由函數的調用方式決定。基本上,它是由被調用的對象決定的。例如,在app.run()中,run方法在app上調用,它將按預期工作。然而,在一個稍微不同的情景

var fn = app.run; 
fn(); 

調用函數時沒有對象,因此this不會設置,從而導致意外結果。這正是你的情況。解決方法是確保你傳遞了可以在任何對象上調用的函數,並使該函數在正確的對象上調用run

+0

非常感謝!我不熟悉它在JavaScript中的工作方式,只是希望能像其他語言一樣工作。 – 2013-02-16 20:59:25

+1

@KarlJacques:你越早解脫自己的期望,就越好。如果所有的語言都一樣,那麼它們就不會是不同的語言。 – 2013-02-16 21:01:18

0

你已經脫離從apprun方法。傳遞一個使它們保持在一起的函數。

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

現在的this.run()的值將是app對象。


而且,也沒有必要爲每application()對象的新run方法。您可以在application.prototype上放置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); 
} 

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)