2012-05-02 34 views
2

我開始嘗試創建一個計時器函數,它可以讓我包裝一個回調函數,以便稍後可以動態改變行爲。在javascript中需要幫助包裝一個函數並正確處理「this」

這使人們普遍認識到,我真的不明白的功能還沒有,絕對不明白與發生的事情「這個」

我有一個測試環境設置jsfiddle

myns = {}; 
myns.somefunc = function(txt) { 
    this.data = txt; 
    this.play = function() { 
     alert(this.data + ' : '+dafunc.data); 
    }; 
}; 

var dafunc = new myns.somefunc('hello world'); 

myns.Timer = function(msec, callback) { 
    this.callback = null; 
    this.timerID = null; 

    this.ding = function() { 
     this.callback(); 
    }; 

    this.set1 = function(msec, callback) { 
     this.stop(); 
     this.callback = callback; 
     this.timerID = setTimeout(this.ding, msec); 
    }; 

    this.set2 = function(msec, callback) { 
     this.callback = callback; 
     var wrappedDing = (function(who) { 
      return function() { 
       who.ding(); 
      }; 
     })(this); 
     this.timerID = setTimeout(wrappedDing, msec); 
    }; 
    //this.set1(msec, callback); 
    this.set2(msec, callback);  
}; 

var ttimer = new myns.Timer(1000, dafunc.play); 

如果我使用set1方法,則回調不起作用。 所以我正在嘗試set2方法。這讓我進入play方法,但「this」不是指somefunc的實例。

我以爲我在正確的軌道上,但混淆'這'讓我感到困惑。

任何線索都會受到歡迎。

回答

1

問題是,不像python這樣的語言,當你拿一個dafunc.play並將它傳遞到別的地方(callback = dafunc.play)時,它忘記了它與dafunc相關聯,你需要使用它的兒子又一個包裝函數,就像你在set2函數中做的那樣。

var ttimer = new myns.Timer(1000, function(){ return dafunc.play(); }); 

自己製作的所有有額外的功能是煩人。你也可以使用綁定的方法是在新的瀏覽器可供選擇:

var wrappedDing = this.ding.bind(this); 

new myns.Timer(1000, dafunc.play.bind(dafunc)); 

或者,如果你需要支持舊版本的IE也可以使用類似的墊片。


最後,如果你不打算利用某種形式的繼承和動態綁定的,你可以改爲重寫代碼使用瓶蓋。既然一切都lexicaly範圍的,你不必擔心this了:

(順便說一句,我結束了簡化的proccess代碼...)

myns = {}; 

myns.somefunc = function(txt) { 
    var obj = { data : txt }; 
    obj.play = function() { 
     alert(obj.data); 
    }; 
    return obj; 
}; 

var dafunc = myns.somefunc('hello world'); 

myns.timer = function(msec, callback) { 
    var timerID = null; 

    var set = function(){ 
     stop(); 
     timerID = setTimeout(callback, msec); 
    }; 

    set(); 

    return { 
     set: set 
    }; 
}; 

var ttimer = myns.timer(1000, dafunc.play); 

還有一最後一件事:如果你不討厭自己使用console.log和瀏覽器的調試器和開發控制檯,而不是使用警報輸出。

+0

額外的包裝功能就像一個魅力。所以謝謝你的快速解決。添加的材料是極好的食物。最後我看到了這種新的綁定方法的用法。 (我的程序需要一個畫布,所以我認爲綁定會在那裏肯定)。我想研究你的簡化並更好地理解它們。感謝幫助。 – Claude

+0

對此警報感到抱歉。我有時使用它作爲停止程序流程的一種方式,以便我可以在Firebug腳本控制檯中檢查觀察值。我一定會轉換爲jsfiddler的console.log。 – Claude

+0

@Claude:不需要對提醒感到抱歉,我只是在這裏向所有人表示^^。 – hugomg