![](/img/trans.png)
[英]How can I unit test anonymous callbacks passed to JavaScript functions?
[英]How is data passed to anonymous functions in JavaScript?
當我將'this'傳遞給匿名函數時:
MyClass.prototype.trigger = function(){
window.setTimeout(function(){this.onTimeout();},1000);
}
我得到一個“this.onTimeout不是一個函數” - 錯誤。 我想在匿名函數執行時'this'不再可用了嗎? 所以我一直這樣做:
MyClass.prototype.trigger = function(){
var me = this
window.setTimeout(function(){me.onTimeout();},1000);
}
這真的是你應該做的事情嗎? 它有點工作,但感覺很奇怪。
然后我們有這個例子:
$(function(){
function MyClass(){
this.queue = new Array();
}
MyClass.prototype.gotAnswer = function(count){
$('body').append("count:"+count+"<br/>");
}
MyClass.prototype.loadAll = function(){
var count = 0;
var item;
while(item = this.queue.pop()){
count++;
var me = this;
$.getJSON("answer.html",{},function(data){me.gotAnswer(count);});
}
}
var o = new MyClass();
o.queue.push(1);
o.queue.push(2);
o.loadAll();
});
這輸出:
2
2
不應該輸出:
1
2
代替? 然后我發現將$ .getJSON語句放在另一個函數中使它全部工作:
MyClass.prototype.loadAll = function(){
var count = 0;
var item;
while(item = this.queue.pop()){
count++;
this.newRequest(count);
}
}
MyClass.prototype.newRequest = function(count){
var me = this;
$.getJSON("answer.html",null,function(data){ me.gotAnswer(count); });
}
這輸出:
1
2
(或者相反。)這里發生了什么? 將變量傳遞給anonnymous函數的正確方法是什么?
抱歉這個令人困惑和冗長的帖子。
你所經歷的是正確的行為 - 這不是一個好的行為,但它是語言的一部分。 在每個函數定義中重置“this”的值。 有四種方法可以調用具有不同方法來設置“this”的函數。
myFunc(param1,param2);這種調用函數的方法總是將“this”重置為全局對象。 這就是你的情況。
myObj.myFunc(param1,param2);毫無疑問,將“this”設置為調用該方法的任何對象。 在這里,“this”==“myObj”。
myFunc.apply(myObj,[param1,param2])這是一個有趣的 - 這里“this”設置為您作為apply方法的第一個參數傳遞的對象 - 就像在沒有該方法的對象上調用方法一樣(注意函數被寫為這樣稱呼)。 默認情況下,所有函數都具有apply方法。
myNewObj = new MyConstructor(param1,param2);當您以這種方式調用函數時,“this”被初始化為一個新對象,該對象從函數的prototype屬性繼承方法和屬性。 在這種情況下,新對象將繼承自MyConstructor.prototype。 此外,如果您未明確返回值,則將返回“this”。
您使用的解決方案是推薦的解決方案 - 將“this”的外部值分配給另一個在您的函數內仍然可見的變量。 我唯一要改變的是將變量稱為“那個”,如TörökGábor所說 - 這是事實上的標准,可能會讓你的代碼更容易為其他程序員閱讀。
你對閉包感到困惑。
對於第一個問題,是的,你是對的,這就是它可以做到的方式。 唯一的區別是有約定命名變量that
保存this
。
MyClass.prototype.trigger = function(){
var that = this;
window.setTimeout(function(){that.onTimeout();},1000);
}
在StackOverflow上已有一個很好的關於此的線程。 檢查問題的答案javascript關閉是如何工作的? 。
你的第二個問題是循環中Javascript閉包的完全重復- 簡單的實際例子 。
如果在新方法中,你將遇到同樣的問題:newRequest你必須使用“for”或“while”語句。 另一個解決方案是創建一個閉包:
像那樣:
$.getJSON("answer.html",{},(function(me){return function(data){me.gotAnswer(count);}})(this));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.