es6函數總結

做用域

  • 一旦設置了默認參數,函數進行聲明初始化時,參數會造成一個單獨的做用域(context)。 等到初始化結束,這個做用域就會消失。這種語法行爲,在不設置參數默認值時,是不會出現的。 見例子:
例子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

rest參數

  • rest 參數搭配的變量是一個數組,該變量將多餘的參數放入數組中,這樣就不須要使用arguments對象了; 見例子:
function add (...value) {
let sum = 0;
for (let i of value) {
sum += i;
}
return sum;
}
add(3, 5, 7);   // 15

箭頭函數

  • () => {}; // 匿名函數
  • n => n + 1;
  • n => ({id: n}); 返回對象要用括號括起來,由於{}被解釋爲代碼塊;

注意點編程

  • 箭頭函數沒有this,準確來講,箭頭函數的this是其函數外的this
  • 不能夠當構造函數
  • 不可以使用argument,可使用rest代替
  • 不可以使用yield命令,箭頭函數不能做爲Generator
  • arguments、super、new.target和this同樣指向外層函數的對應變量

雙冒號運算符

  • ::雙冒號左邊是一個對象,右邊是一個函數
  • 該運算符會自動將左邊的對象,做爲上下文環境(即this對象),綁定到右邊的函數上面

尾調用

見下面幾個例子:數組

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)
  • 上面代碼中,tco函數是尾遞歸優化的實現,它的奧妙就在於狀態變量active。默認狀況下, 這個變量是不激活的。一旦進入尾遞歸優化的過程,這個變量就激活了。而後,每一輪遞歸sum返回的都是undefined,因此就避免了遞歸執行;而accumulated數組存放每一輪sum執行的參數,老是有值的,這就保證了accumulator函數內部的while循環老是會執行。這樣就很巧妙地將「遞歸」改爲了「循環」,然後一輪的參數會取代前一輪的參數,保證了調用棧只有一層。
相關文章
相關標籤/搜索