ES6----函式

happy137發表於2017-12-18

本文主要總結ES6新增的函式的用法及注意點。

函式引數預設值

ES6允許為函式引數設定預設值。用法如下:

function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
複製程式碼

這樣寫的好處是:

  • 比ES5寫法簡潔
  • 便於閱讀程式碼
  • 有利於程式碼優化

需要注意的點:

  • 引數變數是預設宣告的,所以不能用let和const再次宣告。但是var是可以的。
  • 使用引數預設值時,函式不能有同名引數。
  • 引數預設值是惰性求值的。
  • 有預設值的引數最好放到後面,如果放到前面,傳參無法省略;若要使用預設值,需要顯示傳undefined才會觸發預設值
  • 函式的length屬性返回沒有指定預設值的引數個數。而且如果設定的預設值不是尾引數,那麼length屬性不再計入後面的引數。
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
複製程式碼

rest引數

rest引數的引入,用於獲取函式的多餘引數,這樣就不需要使用arguments物件了。

function push(array, ...items) {
  items.forEach(function(item) {
    array.push(item);
    console.log(item);
  });
}

var a = [];
push(a, 1, 2, 3)
複製程式碼

需要注意的點:

  • rest 引數之後不能再有其他引數(即只能是最後一個引數),否則會報錯。
  • 函式的length屬性,不包括 rest 引數。

嚴格模式

ES6規定只要函式引數使用了預設值、解構賦值或者擴充套件運算子,那麼函式內部就不能顯示設定為嚴格模式,否則報錯。 解決方案:

  • 設定全域性性的嚴格模式
'use strict';

function doSomething(a, b = a) {
  // code
}
複製程式碼
  • 把函式包裹在一個無引數的立即執行函式裡
const doSomething = (function () {
  'use strict';
  return function(value = 42) {
    return value;
  };
}());
複製程式碼

name屬性

函式的那麼屬性,返回函式的函式名。 需要注意的點:

  • 將匿名函式賦值給一個變數,ES5的name屬性返回空字串,ES6的name屬性返回實際的函式名。
var f = function () {};

// ES5
f.name // ""

// ES6
f.name // "f"
複製程式碼
  • Function建構函式返回的函式例項,name屬性的值為anonymous。
(new Function).name // "anonymous"
複製程式碼
  • bind返回的函式,name屬性值會加上bound字首。
function foo() {};
foo.bind({}).name // "bound foo"

(function(){}).bind({}).name // "bound "
複製程式碼

箭頭函式

用法很簡單,主要記錄一下需要注意的點。

  • 如果箭頭函式直接返回一個物件,必須在物件外面加上括號,否則會報錯。
// 報錯
let getTempItem = id => { id: id, name: "Temp" };

// 不報錯
let getTempItem = id => ({ id: id, name: "Temp" });
複製程式碼
  • 函式體內的this物件,就是定義時所在的物件,而不是使用時所在的物件。
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42
複製程式碼

箭頭函式的這個特點,使得this指向固定化。根本原因是箭頭函式根本沒有自己的this,導致內部的this就是外層程式碼的this。

  • 不可以當做建構函式使用,即不可以使用new命令,否則會丟擲錯誤。因為箭頭函式實際上沒有this!!!
  • 不可以使用arguments物件,在箭頭函式內部該物件不存在。如果要用,可以使用rest引數代替。
  • 不可以使用yield命令,因此箭頭函式不能用作Generator函式。
  • 箭頭函式內部不存在arguments、super、new.target物件

尾呼叫優化

尾呼叫指的是某個函式的最後一步是呼叫另一個函式。尾呼叫不一定出現在函式尾部,只要是最後一步操作即可。

function f(x) {
  if (x > 0) {
    return m(x)
  }
  return n(x);
}
複製程式碼

上面就是一個尾呼叫的例子。 同時,下面的幾種情況不是尾呼叫。

// 情況一
function f(x){
  let y = g(x);
  return y;
}

// 情況二
function f(x){
  return g(x) + 1;
}

// 情況三
function f(x){
  g(x);
}
複製程式碼

由於函式內部呼叫另一個函式,會形成一個呼叫棧。而尾呼叫是函式的最後一步操作,所以尾呼叫的時候不需要保留外層函式的呼叫幀。直接用內層函式的呼叫幀就可以。這就是尾呼叫優化。

由此可知,我們把函式都寫成尾呼叫,使得每次執行時,呼叫幀只有一項,這會大大節省記憶體。

但是需要注意一點:

  • 只有不再用到外層函式的內部變數,內層函式的呼叫幀才會取代外層函式的呼叫幀,否則無法進行尾呼叫優化。
  • 尾遞迴優化和它類似。
  • ES6的尾呼叫優化只在嚴格模式下開啟,正常模式無效。

相關文章