2012-10-19 19 views
1

假設socket.io使用for循環添加socket.on方法

socketMethods:{ 
    update:function(data){ 
     this.emit("test", data); 
     console.log("socket.update"); 
    }, 
    test:function(data){ 
     this.emit("test", data); 
     console.log("socket.test"); 
    } 
} 

這下面是可能的,並讓我發出的「測試」和「更新」和「測試」和「更新」將被稱爲

socket.on("test", function(data){ 
    dummy.socketMethods.test.call(socket, data); 
}); 
socket.on("update", function(data){ 
    dummy.socketMethods.update.call(socket, data); 
}); 

下面這些是不可能的......每一個將改爲調用「測試」,如果我發出的「測試」或「更新」。如果我使用FOR循環,所有方法將成爲所謂的「最後」方法。

也就是說:如果我切換更新並測試,以便測試是第一次,並且更新次數在socketMethods對象中。 「更新」總是被調用,不管我是否提出要「測試」或「更新」

for(key in dummy.socketMethods){ 
    socket.on(key, function(data){ 
     dummy.socketMethods[key].call(socket, data); 
    }); 
} 



var methods = ["test", "update"]; 
while(methods.length !== 0){ 
    var method = methods.pop(); 
    console.log(method); 
    socket.on(method, function(data){ 
     dummy.socketMethods[method].call(socket, data); 
    }); 
} 



var methods = ["test", "update"]; 
for(var i = 0; i < methods.length; i++){ 
    console.log(i); 
    socket.on(methods[i], function(data){ 
     console.log(i); 
     dummy.socketMethods[methods[i]].call(socket, data); 
    }); 
} 

線索:使用「我」的for循環,有兩個console.logs。第二個console.log返回「2」

爲什麼會發生這種情況?我怎麼能使用for循環來附加我的socketMethods?

回答

5

你使假設封閉「陷阱」它是時的外部函數的變量的值創建常見的錯誤。它沒有。它將引用「陷阱」到外部函數的變量,其值將是在關閉是執行時外部變量具有的任何值。如果你在一個循環中創建閉包,那麼這個值將是循環結束時的值。

解決此問題的方法是創建一個使用外部變量值作爲參數的「封閉」閉包。一種方法是創建一個幫助函數來生成閉包。在你的第一個例子,你可以在每個封閉做

function makeOn(key) { 
    return function(data) { 
    dummy.socketMethods[key].call(socket, data); 
    } 
} 

for(key in dummy.socketMethods){ 
    socket.on(key, makeOn(key)); 
} 

現在,key將被設置爲相應的值新創建的變量(閉包之間的不同)。

也可以使用立即函數調用(有些人稱之爲「自我執行函數」)來更簡潔地做同樣的事情,但也有點不可讀。

+0

因爲這篇文章,我不認爲我可以甚至開始 - 表達我將要學習關閉多少。這工作 - 很簡單,甚至沒有運行兩次。 – iNk