2012-11-01 108 views
0

作爲我正在構建的Web應用程序的一部分,多個命令可以立即從服務器進入。當範圍函數發生Javascript範圍問題

當這些命令被處理時,數據往往會被更新,然後會產生相當大的頁面HTML生成。

當多個相似的命令進來時,程序將處理數據,然後每次都會重新生成部分頁面。這可能會導致大量浪費的處理時間。

因此,我試圖做一個調用堆棧,所以當一個命令被處理時,它會查看命令觸發的函數是否在堆棧中,如果沒有找到它會添加它。


我的問題是保持被調用的函數從調用堆棧在正確的範圍內,同時也能夠消除重複。

基地代碼:

var tools = { 
    functions:{ 
    function1: function(){ 
     return this; 
    }, 
    function2: function(){ 
    } 
    }, 
    unique: function(arr){ 
    var returnArr=[], 
     x, i; 

    for (x=0; x<arr.length; x++){ 
     for (i=(x+1); i<arr.length; i++){ 
     if (arr[x]===arr[i]){ 
      arr.splice(i, 1); 
     } 
     } 
     returnArr.push(arr[x]); 
    } 

    return returnArr; 
    } 
} 

實施例1:

var callstack=[tools.functions.function1, tools.functions.function1]; 

callstack = tools.unique(callstack); 

for (var x=0; x<callstack.length; x++){ 
    console.log(callstack[x](), "should equal tools.functions"); 
} 

此失敗 「本」 將返回[函數()]


實施例2:

var callstack=[ 
    (function(){return tools.functions.function1()}), 
    (function(){return tools.functions.function1()}) 
]; 

callstack = tools.unique(callstack); 

for (var x=0; x<callstack.length; x++){ 
    console.log(callstack[x](), "should equal tools.functions"); 
} 

這會失敗,因爲您不能確保函數是唯一的,所以它仍然會運行兩次函數。


這可以通過周圍使用兩個陣列(一個信守的函數名的軌道,一個持有封裝功能),並保持它們同步進行工作,但我不禁覺得有必須是使用.call的更清晰的方式,但我看不到它。

的jsfiddle:http://jsfiddle.net/Kj6E8/

回答

1

一般地講這是不可能保存在您需要的方式this值。只要將這些函數推入數組中,這些函數曾經駐留的對象就會丟失。

如果您只是在單個對象上調用函數,則需要以某種方式將函數綁定到該對象。有很多方法可以做到這一點,例如,您可以傳遞對象來將這些函數綁定到您的獨特函數中。

http://jsfiddle.net/8WAZb/1/

var tools = { 
    functions:{ 
    function1: function(){ 
     return this; 
    }, 
    function2: function(){ 
    } 
    }, 
    unique: function(arr, o){ 
    var returnArr=[], 
     x, i; 

    for (x=0; x<arr.length; x++){ 
     for (i=(x+1); i<arr.length; i++){ 
     if (arr[x]===arr[i]){ 
      arr.splice(i, 1); 
     } 
     } 
     returnArr.push(this.bind(arr[x], o)); 
    } 

    return returnArr; 
    }, 
    bind: function(f, o) { 
     return function() { 
      return f.apply(o, arguments); 
     } 
    } 
} 

console.info("Example 1:"); 
var callstack=[tools.functions.function1, tools.functions.function1]; 
callstack = tools.unique(callstack, tools.functions); 
console.log("Callstack:",callstack); 
for (var x=0; x<callstack.length; x++){ 
    console.log(callstack[x](), "should equal tools.functions"); 
} 

當推斷的this價值實際上取決於當你在作用域對象的方式和時間。據推測,在調用堆棧創建階段期間,您可能更有可能在該範圍內創建該對象,並且可能不一定在您希望調用該調用堆棧中的函數的位置。如果是這樣的話,儘可能早地綁定(即在縮減到一個獨特的調用堆棧的過程中),這似乎是一個明智的選擇。

+0

謝謝,我去了這個修改後的版本。 http://jsfiddle.net/DCk8c/ – Doug

1

在JavaScript中,this從外部調用者定義的,所以當你:

callstack[x]() 

您帶來window範圍進入功能。如果你想在tools.functions對象帶來,你需要做的:

callstack[x].call(tools.functions); 

http://jsfiddle.net/Yv4sM/

+0

謝謝。不幸的是,並不是所有的函數都位於同一個命名空間中,因此我不能只在最後一次推送單個調用。可能我可以解決像這樣的問題http://jsfiddle.net/Kj6E8/1/不幸的是,我認爲這可能是最乾淨的我可以得到它,因爲我似乎無法找到找到父對象的方式函數沒有遍歷所有東西= [ – Doug