2013-05-10 30 views
1

我在curring功能和部分應用程序的工作, 我試圖改善功能schonfinkelize:如何捕捉一個函數的參數個數需要(柯里函數部分應用程序)

 function schonfinkelize(fn){ 
      var 
       slice = Array.prototype.slice, 
       stored_args = slice.call(arguments, 1); 
      return function(){ 
       var 
        new_args = slice.call(arguments), 
        args = stored_args.concat(new_args); 

       return fn.apply(null, args); 
      } 
     } 

此功能允許參數作爲一個功能參數作爲參數(部分應用程序)傳遞函數的所以第一次的一部分返回一個函數,然後當你再次觸發該函數的結果。

function add(x, y, z){ 
    return x + y + z; 
} 

var val = schonfinkelize(add, 1, 2); 

console.log(val(3)) // console output--> 6 

我要檢查內schonfinkelize參數的數量需要的功能,「添加」(但它應該與每一個功能的工作),所以我可以選擇何時返回另一個函數或函數的直接結果「添加」 。

bacause如果我用schonfinkelize這樣:

var val2 = schonfinkelize(add, 1, 2, 3); 
console.log(val2) // --> function 
console.log(val2()) // --> 6 

我不得不解僱功能兩地時間,而不是想避免這種情況,如果參數是足夠直接定義值。


一個可能的解決方案如下:

 function schonfinkelize(fn){ 
      var 
       slice = Array.prototype.slice, 
       stored_args = slice.call(arguments, 1); 


       //* I have added this ******** 
       if(fn.apply(null, stored_args)) 
        return fn.apply(null, stored_args); 
       //**************************** 

      return function(){ 
       var 
        new_args = slice.call(arguments), 
        args = stored_args.concat(new_args); 

       return fn.apply(null, args); 
      } 
     } 

可能是因爲它會立即返回結果,如果fn.apply(NULL,stored_args)回報的東西是不是 「空」或「NaN」,但我認爲並不是真正的高性能,然後我想用這些論據進行工作。

+1

*如果*您可以假設傳遞的函數只需要定義多少個參數,然後就可以找出函數的'.length'屬性有多少。所以你的'add'函數將會有'add.length; // 3'。那麼你可以將這個數字與傳遞給你返回函數的參數數量進行比較。 – 2013-05-10 11:44:19

+0

我試圖避免屬性.length因爲需要傳遞的所有參數的數量,所以可能是每個數量的數量,但如果我遵循你的推理,你是對的。我也認爲也適用於附加範圍,如 v.len = 3(如斯佩蘭斯基丹尼爾的迴應) 但我希望找到一個本地適當的功能,但在這一點上,我認爲它不存在... – 2013-05-10 12:47:39

+0

函數的本地屬性是我在上面的評論中描述的。函數具有'.length'屬性,該屬性描述爲該函數定義了多少個參數。是的,一個人可以添加一個'.len',但爲什麼同一個人不會簡單地定義合適的參數數量? – 2013-05-10 12:54:33

回答

1

只要你在的地方放,對於傳遞函數定義的參數反映實際數量將被最終接收參數的要求,您可以使用函數的.length財產做比較通過論據傳遞給預期的論點。

function schonfinkelize(fn) { 
    if (fn.length === arguments.length - 1) 
     return fn.apply(this, [].slice.call(arguments, 1)); 

    var 
     slice = Array.prototype.slice, 
     stored_args = slice.call(arguments, 1); 
    return function(){ 
     var 
      new_args = slice.call(arguments), 
      args = stored_args.concat(new_args); 

     return fn.apply(null, args); 
    } 
} 

邊注...你能避免.slice()如果你在一個新的變量緩存fn,並與this值覆蓋第一個參數,然後用.call.apply() ...

if (fn.length === arguments.length - 1) { 
     var func = fn; 
     arguments[0] = this; 
     return func.call.apply(func, arguments); 
    } 

嚴格模式瀏覽器,你甚至可以避免有新的變量,因爲參數不再映射到arguments中的變化。但是這在瀏覽器中不支持嚴格模式

1

我不認爲有一個確定任意函數的參數數量的正確方法。如果需要,我更喜歡在函數中存儲len,並檢查它是否已定義,如果是,則返回剛剛返回值的函數。

function schonfinkelize(fn){ 
    var 
    slice = Array.prototype.slice, 
    stored_args = slice.call(arguments, 1); 

    if (fn.len != undefined && fn.len == stored_args.length) { 
    var val = fn.apply(null, stored_args); 

    return function() { 
     return val; 
    }; 
    } 

    return function() { 
    var 
     new_args = slice.call(arguments), 
     args = stored_args.concat(new_args); 

    return fn.apply(null, args); 
    }; 
} 

var f = function (a, b, c) { 
    return a + b + c; 
}; 

f.len = 3; 

var g = schonfinkelize(f, 1, 2); 
alert(g); // function() { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); }; 
alert(g(3)); // 6 

var g = schonfinkelize(f, 1, 2, 3); 
alert(g); // function() { return val; }; 
alert(g()); // 6 
+0

我以爲同樣的事情,但我希望有一個本機禮貌用於發現這個數字,但似乎它不存在。 – 2013-05-10 13:01:20

0

我想提出一個個人演化的代碼,但我不得不說,謝謝斜視已解決問題,只是建議我使用屬性.length。 的一個新的水平在我看來允許創建能夠在部分功能被稱爲每次你想,直到你完成填寫所有的參數,我還簡化了代碼:

 function schonfinkelize(fn, stored_args){ 
      if(fn.length == stored_args.length) 
       return fn.apply(null, stored_args); 

      return function(){ 
       var 
        new_args = arguments[0], 
        args = stored_args.concat(new_args); 

       if(fn.length == args.length) 
        return fn.apply(null, args); 

       return schonfinkelize(fn, args); 
      } 
     } 


     function add(x, y, w, z){ 
      return x + y + w + z; 
     } 


     var 
      val = schonfinkelize(add, [1, 2, 3, 4]), 
      val2 = schonfinkelize(add, [1, 2]), 
      val3 = schonfinkelize(add, [1]); 


     // checking 
     console.log(val);   // output --> 10 // called only 1 time 
     console.log(val2([3, 4])); // output --> 10 // called in 2 times 

     val3 = val3([2]); 
     val3 = val3([3]); 
     console.log(val3([4]));  // output --> 10 // called 4 times! 
相關問題