2013-06-29 87 views
1

鑑於此函數調用:返回函數數組:創建關閉

var funcs = obj.getClosures([2, 4, 6, 8], function(x) { 
    return x*x; 
}); 

我有以下功能:

getClosures : function(arr, fn) { 
    var funcs = []; 
    var array = arr; 
    var i = 0; 
    var l = array.length; 

    (function(i, array) { 

     for (; i < l; i++) { 
      funcs[i] = function(i, array) { 
       return fn(array[i]); 
      }; 
     } 

    }(i, array)); 

    return funcs; 

}, 

我希望能夠遍歷返回的數組和得到陣列中每個物品的平方根值如下:

for (var i = 0; i < arr.length; i++) { 
    funcs[i](); 
} 

每次通過的結果循環:4,16,36,64

不應該我的funcs數組在每個索引中都有函數引用,可以使用相關參數值輕鬆調用它們嗎?我哪裏做錯了?

+0

我suprprised它做了一些事情。它應該拋出錯誤,因爲你不會傳遞任何參數給函數調用('funcs [i]()')。 –

+0

如果提供更多或更少的參數,JavaScript不會產生錯誤。相反,它會忽略多餘的或者將缺少的設置爲「undefined」 – mishik

+0

@mishik:如果你的評論是爲了迴應我的,即使你是正確的,如果'array'是undefined,array [i]'會拋出一個錯誤'(如果沒有參數傳遞的話就是這種情況)。 –

回答

2

有多個 「問題」:

的IIFE (function(i, array) { ... }(i, array));沒有任何好處可言這裏。如果刪除它,代碼將具有完全相同的行爲。如果要捕獲當前值iarray,則必須將其移動到for循環中。

您的函數定義不正確。

funcs[i] = function(i, array) { 
    return fn(array[i]); 
}; 

在函數內部,array[i]將參照參數你傳遞給函數。如果你沒有通過,它們將是undefined,代碼將會出錯。也就是說,這一定義,你就必須執行,像這樣的功能:

for (var i = 0; i < arr.length; i++) { 
    funcs[i](i, array); 
} 

哪一種失敗擺在首位生成功能的目的。

如果要創建一個可以訪問定義函數的作用域的iarray的閉包,請不要定義具有相同名稱的參數。

可能的解決辦法:

for (var i = 0, l = array.length; i < l; i++) { 
    (function(i) { 
     funcs[i] = function() { 
      return fn(array[i]); 
     }; 
    }(i)); 
} 

或者更簡單,如果你的代碼在環境中運行支持.map

getClosures: function(arr, fn) { 
    return arr.map(function(v) { 
     return function() { 
      fn(v); 
     }; 
    }); 
}, 

相關的問題:

+0

+1;或者,在IIFE中移動'funcs [i] ='。這使您可以爲每個IIFE分配多個處理程序,並且更具慣用性的IMO。 –

+0

@Jan:我真的想知道選擇哪種方法。我現在改了它,因爲我認爲它離原始代碼更近一些,可能會更容易理解。謝謝! –

+0

謝謝Felix!這是我學習關閉時的練習,你的觀點非常有幫助! IIFE在循環之外並且認爲我必須在每個函數中嵌套參數的錯誤現在對我來說更加清晰。這變得越來越簡單:-) –

0

閱讀Function.prototype.bind

var obj = { 
getClosures : function(arr, fn) { 
    var funcs = []; 
    var array = arr; 
    var i = 0; 
    var l = array.length; 

    (function(i, array) { 

     for (; i < l; i++) { 
      funcs[i] = function(i, array) { 
       return fn(array[i]); 
      }.bind(this,i,array); 
     } 

    }(i, array)); 

    return funcs; 

} 
} 

var funcs = obj.getClosures([2, 4, 6, 8], function(x) { 
    return x*x; 
}); 

for (var i = 0; i < funcs.length; i++) { 
    console.log(funcs[i]()); 
} 

輸出:

4 
16 
36 
64 

它的工作原理,因爲JavaScript的1.8.5(火狐4)。我不知道其他瀏覽器,但有舊版本的實施(也應該在舊版瀏覽器上工作)