例子1: let x = 1; function func (x, y = x) { console.log(y) // 輸出2 } func(2) 例子二: let x = 1; function f(y = x) { let x = 2; console.log(y); // 輸出1 } f() 例子三:報錯 function f(y = x) { let x = 2; console.log(y); } f() // ReferenceError: x is not defined
function add (...value) { let sum = 0; for (let i of value) { sum += i; } return sum; } add(3, 5, 7); // 15
注意點編程
見下面幾個例子:數組
function factorial(n) { if (n === 1) return 1; return n * factorial(n - 1); } factorial(5)
複雜度爲o(n) 太大會形成堆棧溢出app
function factorial(n, total) { if (n === 1) return total; return factorial(n - 1, n * total); } factorial(5, 1) //
複雜度爲哦o(1)編程語言
尾遞歸函數的改寫:函數式編程
尾遞歸的實現,每每須要改寫遞歸函數,確保最後一步只調用自身。作到這一點的方法,就是把全部用到的內部變量改寫成函數的參數函數
遞歸本質上是一種循環操做。純粹的函數式編程語言沒有循環操做命令,全部的循環都用遞歸實現,這就是爲何尾遞歸對這些語言極其重要。 對於其餘支持「尾調用優化」的語言(好比 Lua,ES6),只須要知道循環能夠用遞歸代替,而一旦使用遞歸,就最好使用尾遞歸。優化
解決方案: 一、蹦牀函數的一個實現,它接受一個函數f做爲參數。只要f執行後返回一個函數,就繼續執行。 注意,這裏是返回一個函數,而後執行該函數,而不是函數裏面調用函數,這樣就避免了遞歸執行,從而就消除了調用棧過大的問題。this
例子:rest
function trampoline(f) { while (f && f instanceof Function) { f = f(); } return f; } function sum(x, y) { if (y > 0) { return sum.bind(null, x + 1, y - 1); } else { return x; } } trampoline(sum(1, 100000)) // 100001
二、真的優化方案code
function tco(f) { var value; var active = false; var accumulated = []; return function accumulator() { accumulated.push(arguments); if (!active) { active = true; while (accumulated.length) { value = f.apply(this, accumulated.shift()); } active = false; return value; } }; } var sum = tco(function(x, y) { if (y > 0) { return sum(x + 1, y - 1) } else { return x } }); sum(1, 100000)