簡體   English   中英

訪問實例方法時的JavaScript OO問題

[英]JavaScript OO issue when accessing instance methods

我使用過一些有關JavaScript中OOP的教程。 一切順利,直到我遇到了以下問題...

Result of expression 'this.prepareFrame' [undefined] is not a function.

好。 我正在使用prototype並使用this關鍵字。

在這里查看我的app.js頁面...

// Plain "main" function called by the html page, like <script>main()</script>. This works nicely:

    function main() {
    engine = new AbstractEngine();
    engine.init();
    }

// Next creates a new instance of my AbstractEngine class. Seems to work so far:

    function AbstractEngine() {}

// The init() method we called is defined afterwards:

    AbstractEngine.prototype.init = function() {
    this.initLoop();
    }

// remark: I'm using "this", and according to the debugger, "this" refers to the AbstractEngine we made an instance of.

// Next, we define the initLoop method:

    AbstractEngine.prototype.initLoop = function() {
    setInterval(this.tick, 1000 / 30);
    }

// Fine, everything works fine so far. Now get to define the "tick" method:

    AbstractEngine.prototype.tick = function() {
    this.prepareFrame();
    this.update();
    }

// Ok, we're in trouble. The error message is output to the console and I don't understand why... The prepareFrame() and update() methods are defined right afterwards:

    AbstractEngine.prototype.update = function() {
    console.log('updating!');
    }

    AbstractEngine.prototype.prepareFrame = function() {
    console.log('preparing frame');
    }

// I read my code twice, but didn't find beginner's mistakes like typo or whatever. But well, cosnider I'm a beginner

您需要將initLoop的定義更改為以下內容:

AbstractEngine.prototype.initLoop = function() {
    var that = this;

    setInterval(function () {
        that.tick();
    }, 1000 / 30);
}

這是因為該決議this被延遲,直到執行時間和執行的時間間隔時, this指向window ,而不是你的實例AbstractEngine

通過將對tick的調用包裝在一個匿名函數中,我們創建了一個閉包,它允許我們捕獲that閉包(將其設置為this )。 通過在實例舊的 this)上調用方法 tick ,我們可以恢復“ this”的值。

這個:

setInterval(this.tick, 1000 / 30);

應該:

var that = this;
setInterval(function () { that.tick(); }, 1000 / 30);

或者:

setInterval(this.tick.bind(this), 1000 / 30);

說明:當您簡單地傳遞this.tick ,與執行以下操作相同:

var temp = this.tick;
setInterval(temp, 1000 / 30);

但是現在,當調用temp時,JavaScript不知道this指針應該是什么。 該信息會丟失,最終會綁定到全局對象( window ),如果處於嚴格模式下則將綁定為null

因此,您需要以某種方式確保使用適當的this指針作為一個方法來調用this.tick 有兩種方法可以做到這一點:

  1. 通過將其包裝在捕獲var that = this的閉包中,您可以正確地調用that.tick作為原始this指針上的方法。
  2. 或通過bind()this.tick函數this進行調用,可以確保每次都使用適當的this調用該方法:換句話說,您甚至可以執行var temp = this.tick.bind(this)setInterval(temp, 1000 / 30)

請注意, bind在較舊的瀏覽器中不可用(特別是IE <= 8以及到目前為止(包括5.1)及以下的所有Safari ),在這種情況下,您將需要es5-shim之類的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM