2013-08-05 21 views
-1

我試圖讓未來與封閉:在JavaScript中關閉 - 什麼是錯的?

function func(number) { 
    var result = number; 

    var res = function(num) { 
     return result + num; 
    }; 
    return res; 
} 

var result = func(2)(3)(4)(5)(3); 
console.log(result); // 17 

我需要接受2 + 3 + 4 + 5 + 3 = 17 但我得到了一個錯誤:未捕獲的類型錯誤:數量不是一個函數

+9

這傷害了我的大腦。你可以返回一個函數或數字,而不是兩個.. –

+0

@MikeChristensen:其實,你可以通過檢查'arguments.length'同時返回。 – SLaks

+4

@SLaks - 哦,並把一個'()'在鏈的末尾?是的,這會是一個令你的同事惱火的聰明方式。 –

回答

8

你在濫用你的功能。

func(2)返回res函數。
使用(3)調用該函數將返回5(通過return result + num)。

5不是一個函數,所以(4)提供了一個錯誤。

+0

我明白了,但幫助我找到正確的。 –

+0

@ user2056866很難看出這會有什麼實際用途,所以很可能這是作業。你想做一個遞歸函數嗎?如果是這樣的話,你有點偏離。 – JJJ

+0

只是爲了有趣,我試圖通過關閉來完成。 –

3

那麼,(2)(3)部分是正確的。調用func(2)會返回你res,這是一個函數。但是,打電話(3)會返回給您res,這是一個數字的結果。所以當你嘗試打電話時(4),問題就出現了。

對於你想要做的,我沒有看到Javascript會如何預測你是在鏈的末尾,並決定返回一個數字而不是函數。也許你可以以某種方式返回一個函數,具有使用對象屬性的「結果」屬性,但主要是我只是好奇你爲什麼要嘗試這樣做。顯然,對於你的具體例子,最簡單的方法就是將數字加在一起,但我猜你會進一步處理一些事情。

+0

是的,它只是爲了有趣。但我仍然不知道如何纔是正確的。 –

+0

就像我說過的,你用這種方式調用它的整個方法很奇怪。返回一個可鏈式調用函數的對象會更容易被接受嗎?即'func()。addmore(3).addmore(5).addmore(7).getResult()'?這通常是JQuery所做的。 – Katana314

-1

如果你想繼續調用它,你需要不斷返回一個函數,直到你想要你的答案。例如5調用

function func(number) { 
    var result = number, 
     iteration = 0, 
     fn = function (num) { 
      result += num; 
      if (++iteration < 4) return fn; 
      return result; 
     }; 
    return fn; 
} 
func(2)(3)(4)(5)(3); // 17 

你也可以做更多的長度的東西是這樣的

function func(number) { 
    var result = number, 
     fn = function() { 
      var i; 
      for (i = 0; i < arguments.length; ++i) 
       result += arguments[i]; 
      if (i !== 0) return fn; 
      return result; 
     }; 
    return fn; 
} 
func(2)(3, 4, 5)(3)(); // 17 
+0

@downvoter,請解釋 –

+3

我沒有downvoted你的答案,但它只適用於這些許多數量的()。 它不是動態的。 –

+1

@AmoghTalpallikar我寫它爲OPs的例子,編輯一個有點不同 –

8

你無論如何都以突出鏈,你要去哪裏返回結果數量,而不是結束的另一個功能。你可以選擇:

  • 讓它返回一個固定次數的函數 - 這是使用你喜歡的語法的唯一方法,但它很無聊。看看@PaulS'的答案。您可能會使第一次調用(func(n))提供多少個參數sumcurried的編號。
  • 在某些情況下返回結果,例如函數被調用時沒有參數(@PaulS'第二次執行)或具有特殊值(@ AmoghTalpallikar答案中的null)。
  • 在函數對象上創建一個返回值的方法。 valueOf()非常適合,因爲當函數被轉換爲原始值時它將被調用。看到它在行動:

    function func(x) { 
        function ret(y) { 
         return func(x+y); 
        } 
        ret.valueOf = function() { 
         return x; 
        }; 
        return ret; 
    } 
    
    func(2) // Function 
    func(2).valueOf() // 2 
    func(2)(3) // Function 
    func(2)(3).valueOf() // 5 
    func(2)(3)(4)(5)(3) // Function 
    func(2)(3)(4)(5)(3)+0 // 17 
    
+0

在我的版本,雖然。如果我打電話。 (4)(5) 結果變成9. nxt time f(1)(3)(null)將會給出13而不是4! :( –

+0

'+ 0'爲+1的一個很好的黑客;) – metadings

+0

這真棒! –

0

我檢舉這個重複的,但由於這種替代也從這個問題缺少我會在這裏添加它。如果我理解正確的話,爲什麼你會認爲這是有趣的(具有順序地施加到值的列表中的任意函數,積累的結果),你也應該看看reduce

function sum(a, b) { 
    return a + b; 
} 

a = [2, 3, 4, 5, 3]; 

b = a.reduce(sum); 
+0

如果'a'是空數組,則不要忘記初始化reduce。 – naomik

0

另一種解決方案可能是隻爲了得到結果而調用沒有參數的函數,但如果用params調用它就會增加總和。

function add() { 
 
    var sum = 0; 
 
    var closure = function() { 
 
    sum = Array.prototype.slice.call(arguments).reduce(function(total, num) { 
 
     return total + num; 
 
    }, sum); 
 
    return arguments.length ? closure : sum; 
 
    }; 
 
    return closure.apply(null, arguments); 
 
} 
 

 
console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)); // function(){} 
 
console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)()); // 30;

0

我們可以使用幾個輔助函數identitysumk利用它輕鬆的工作。

sumk使用的延續,以保持待處理的堆疊添加計算和與0展開棧每當第一()被調用。

const identity = x => x 
 

 
const sumk = (x,k) => 
 
    x === undefined ? k(0) : y => sumk(y, next => k(x + next)) 
 

 
const sum = x => sumk(x, identity) 
 

 
console.log(sum())    // 0 
 
console.log(sum(1)())    // 1 
 
console.log(sum(1)(2)())   // 3 
 
console.log(sum(1)(2)(3)())  // 6 
 
console.log(sum(1)(2)(3)(4)()) // 10 
 
console.log(sum(1)(2)(3)(4)(5)()) // 15