【ES6系列】函數部分

箭頭函數

在以前ES5的版本中,咱們定義一個函數的形式以下:數組

function a() {
  // do something……
}

可是在ES6中,則新增了箭頭函數的方式,ES6中容許使用「箭頭」(=>)來定義函數。函數

() => {
  // do something……
}

其中()中表明的是參數部門,{}中是函數體部分。
若是箭頭函數不須要參數或者須要多個參數時,須要使用一個()來包裹,當只有一個參數時,能夠省略()工具

var f = () => 5;
// 等同於
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同於
var sum = function(num1, num2) {
  return num1 + num2;
};

var f = v => v;

// 等同於
var f = function (v) {
  return v;
};

當咱們在函數中返回一個對象時,以前的寫法是:優化

var f = function(id) {
  return {
    id: id,
    name: "name"
  }
}

此時若是改成箭頭函數的方式來寫時,須要注意的是,因爲在ES6中{}表明了一個代碼塊,因此在返回一個對象的時候,須要在對象{}外面使用括號包起來:this

let f = id => ({id: id, name: "name"})

若是箭頭函數只有一行語句,且不須要返回值,能夠採用下面的寫法,就不用寫大括號了。spa

let fn = () => void doesNotReturn();

不難發現,ES6中的箭頭函數相對ES5中的函數的寫法更加的簡潔方便prototype

const isEven = n => n % 2 == 0;
const square = n => n * n;

如上面只是簡單地兩行,就定義了兩個經常使用的工具函數。按照以前的寫法則會書寫多行。特別是在針對回調函數的時候,更可以起到簡化的做用:rest

// ES5的寫法
var evens = [1,2,3,4,5];
var odds = evens.map(function(v){
  return v + 1
})

// ES6的寫法

let evens = [1,2,3,4,5];
let odds = evens.map(v => v + 1)

箭頭函數的this的綁定

箭頭函數和普通函數的另外一個區別,在於this的綁定。例如:code

var factory = function() {
  this.a = "a";
  this.b = "b";
  this.c = {
    a : "a+",
    b : function() {
      return this.a
    }
  }
}
console.log(new factory().c.b()) // "a+"

經過上面的代碼執行能夠看出,獲得的結果是「a+」,從而能夠看出this.a指向的是c.a。有人曾總結過this的指向是該函數被調用的對象。此處b是c調用的,因此指向c中的a。如今修改成ES6的箭頭函數的寫法:對象

let factory = function() {
  this.a = "a";
  this.b = "b";
  this.c = {
    a : "a+",
    b : () => {
      return this.a
    }
  }
}
console.log(new factory().c.b()) // "a"

執行上面的代碼發現,輸出的結果是「a」,這又是爲何呢?請看下圖所示
圖片描述

注意點

箭頭函數有幾個使用注意點

  • (1)函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。這個咱們在上面的例子中也已經見到過了,再舉一個比較常見的例子:

在涉及到setTimeout和setInterval時,咱們以前的方法是在調用前將函數體內的this經過賦值給一個變量的方法,使得可以在setTimeout和setInterval的回調函數中使用函數體的this

function foo() {
  this.id = "111"; 
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

可是在ES6中在使用箭頭函數以後則再也不須要進行賦值替換而能直接使用函數體中的this

function foo() {
  this.id = "111"; 
  setTimeout(()=>{
      console.log(this.id);
  }, 100);
}

this指向的固定化,並非由於箭頭函數內部有綁定this的機制,實際緣由是箭頭函數根本沒有本身的this,致使內部的this就是外層代碼塊的this。正是由於它沒有this,因此也就不能用做構造函數。

除了this,如下三個變量在箭頭函數之中也是不存在的,指向外層函數的對應變量:arguments、super、new.target

  • (2)不能夠看成構造函數,也就是說,不可使用new命令,不然會拋出一個錯誤。
  • (3)不可使用arguments對象,該對象在函數體內不存在。若是要用,能夠用 rest 參數代替(下面會講解rest參數)。
  • (4)不可使用yield命令,所以箭頭函數不能用做 Generator 函數,這部分在後面具體遇到時再進行說明。

函數的默認參數

對於帶有參數的函數,咱們每每在一些狀況下須要給出一個默認值的設置,當不傳入參數時,也能確保函數可以正常執行。在ES5中,咱們的寫法每每以下:

function f(x, y, z) {
  if(y === undefined) {
    y = 7;
  }
  if(z === undefined) {
    z = 5;
  }
  return x + y + z
}
console.log(f(1,3));

在ES6中容許爲函數的參數設置默認值,即直接寫在參數定義的後面。

function f(x, y = 7, z = 5) {
  return x + y + z
}
console.log(f(1,3));

這段代碼和上面的執行結果是一致的,能夠看出函數默認值的寫法使得函數定義更加的簡潔清晰。
ES6 的寫法還有兩個好處:

  • 首先,閱讀代碼的人,能夠馬上意識到哪些參數是能夠省略的,不用查看函數體或文檔;
  • 其次,有利於未來的代碼優化,即便將來的版本在對外接口中,完全拿掉這個參數,也不會致使之前的代碼沒法運行。

應用

另外,在上面的處理中,咱們並無針對x的賦值進行驗證,這樣當在沒有給出x的值的時候,函數會致使報錯。這個時候,咱們能夠來寫一個非空驗證的方法,來給函數添加校驗。

function checkParameter() {
    throw new Error('can\'t be empty')
}
function f(x = checkParameter(), y = 7, z = 5) {
  return x + y + z
}
console.log(f(1,3));
try{
  f()
} catch(e) {
  console.log(e)
} finally {
  
}

這樣給x設置默認值的方式來執行校驗函數,就能夠確認x的賦值的有效性了。這也是函數默認值的一種使用技巧。

rest參數

上面針對參數默認值作了說明,下面咱們考慮一下一個概念,可變參數,好比咱們如今來作一個求和運算的函數,可是是幾個數的求和是不必定的,按照ES5中的處理,咱們的寫法:

function sum() {
  var array = Array.prototype.slice.call(arguments);
  // arguments對象不是數組,而是一個相似數組的對象。因此爲了使用數組的方法,必須使用Array.prototype.slice.call先將其轉爲數組。
  var sum = 0;
  array.forEach(function(item){
    sum += item * 1
  })
  return sum;
}

sum(1,2,3,4)

主要是經過arguments來獲取函數的參數列表來獲取參數。可是在ES6中卻並不須要這麼麻煩,ES6 引入 rest 參數(形式爲...變量名),用於獲取函數的多餘參數,這樣就不須要使用arguments對象了。rest 參數搭配的變量是一個數組,該變量將多餘的參數放入數組中。

function sum(...a) {
  var sum = 0;
  a.forEach(item => sum+= item*1)
  return sum;
}
sum(1,2,3,4)

經過ES6的rest參數,可以更加簡潔的來實現不定參數的函數的實現。rest參數是一個真正的數組,數組特有的方法均可以使用,徹底比上面經過arguments的方法更加天然、簡潔。

注:rest參數以後不能再有其餘參數(即只能是最後一個參數)。

小結

本次主要針對ES6中對於函數部分的相關擴展內容做了梳理,並無很是的全面,而是選擇其中比較經常使用比較重要的箭頭函數、函數默認值和rest參數這幾部分進行了說明。更加細緻的體會仍是須要在後續的不斷使用中進行增強和熟悉。
相關文章
相關標籤/搜索