ES6函數的擴展

函數的擴展咱們能夠從三個方面來了解與認識:數組

  • 參數的默認值
  • 箭頭函數
  • 關於尾調用的優化

參數的默認值

ES6 以前,咱們不能直接爲函數的參數指定默認值,只能採用變通的方法。而 ES6 中容許咱們直接爲函數的參數設置默認值,經過等號 = 直接在小括號中給參數賦值。閉包

示例:
function log(name, age = 18) {
    console.log(name, age);
}
console.log('xkd');         // 輸出: xkd
console.log('summer', 20);  // 輸出: summer 20
console.log('mark', '');    // 輸出: mark

若是函數帶有某一個參數,則表示這個參數變量已經默認聲明,咱們不可使用 let 或者 const 再次聲明這個變量。函數

function xkd(a = 1) {
    let a = 2;
}

// 報錯:SyntaxError: Identifier 'a' has already been declared

還須要注意的是,在使用函數默認參數時,不容許有同名參數:優化

function week(a, a, b = 100) {
    /* ... */
}
// 報錯信息: SyntaxError: Duplicate parameter name not allowed in this context

參數默認值是惰性求值:this

let a = 100;
function xkd(sum = a + 1) {
    console.log(sum);
}
xkd(); // 輸出:101

rest不定參數

ES6 引入 rest 參數,不定參數用來表示不肯定參數個數,由 ... 加上一個具名參數標識符組成。rest

示例:
function add(...values) {
    let sum = 0;
    for (var val of values) {
        sum += val;
    }
    return sum;
}
console.log(add(10, 5, 7));  // 輸出:22

上面代碼的 add 函數是一個求和函數,利用 rest 參數,能夠向該函數傳入任意數目的參數。code

注意 rest 參數只能放在參數組的最後,而且有且只有一個不定參數,這個參數後面不能再有其餘參數,不然會報錯。orm

function func(a, ...b, c) {
    // ...
}
// 報錯:SyntaxError: Rest parameter must be last formal parameter

若是咱們要使用函數的 length 屬性來獲取參數的個數,是不包括 rest 參數的。對象

function func1(a, b){
    //...
}
function func2(a, b, ...c){
    //...
}
console.log(func1.length);  // 輸出: 2
console.log(func2.length);  // 輸出: 2

name屬性

函數的 name 屬性,能夠用於返回該函數的函數名。內存

示例:
function xkd() {
    console.log(xkd.name);  // 輸出:xkd
}
xkd();

也能夠寫成:

var xkd = function() {}
console.log(xkd.name); // 輸出:xkd

箭頭函數

ES6 中容許使用箭頭 => 來定義函數,這樣定義的函數叫作箭頭函數。箭頭函數主要的兩點是:它的 this 指向是在它當時定義所在的區域,還一個是它沒有一個做用域的提高。

示例:
var x = function (y) {
    return y;
}

上述函數使用箭頭函數來寫,能夠寫成:

var x = y => y;

若是箭頭函數不須要參數或須要多個參數,就使用一個圓括號表明參數部分。

示例:

例以下面這個求兩數之和的函數:

var sum = function(num1, num2) {
    return num1 + num2;
}

等同於以下所示箭頭函數的寫法:

var sum = (num1, num2) => num1 + num2;

若是箭頭函數的代碼塊部分多於一條語句,就要使用大括號將它們括起來,而且使用return語句返回。

示例:
var sum = (num1, num2) => { return num1 + num2; }

因爲大括號被解釋爲代碼塊,因此若是箭頭函數直接返回一個對象,必須在對象外面加上括號,不然會報錯。

示例:
let obj = age => ({ name: "xkd", age:age });

箭頭函數能夠與變量解構結合使用。

示例:
const full = ({ first, last }) => first + ' ' + last;

// 等同於
function full(person) {
  return person.first + ' ' + person.last;
}

箭頭函數使用時須要注意的一下幾個問題:

  • 函數體內的 this 對象指向的是定義時所在的對象,而不是使用時所在的對象。
  • 不能夠看成構造函數,也就是說不可使用 new 命令。
  • 不可使用 arguments 對象,可使用 rest 參數替代。
  • 不可使用 yield 命令,所以箭頭函數不能用做 Generator 函數。

關於尾調用的優化

尾調用就是指某個函數的最後一步是調用另外一個函數,不適用於外部變量時只保留內層函數的調用幀。

示例:

例以下面這個 func() 函數中的最後一步是調用函數 show(),這就叫尾調用:

function func(x) {
    return show(x);
}

若是在調用一個函數以後,還有其餘的操做,則不屬於尾調用。

注意,尾調用不必定出如今函數尾部,只要是最後一步操做便可,例以下面這段代碼中:

function func(x) {
    if (x > 0) {
      return f1(x)
    }
    return f2(x);
}

函數 f1f2 都屬於尾調用,由於這兩個函數調用都是函數 func 的最後一步操做。

ES5 中,尾調用的實現是建立一個新的棧幀 stack frame, 將其推入調用棧中表示函數調用。因此每個未用完的棧幀都會保存在內存中,當調用棧變得過大時會形成程序問題,也就是咱們常說的棧溢出。

ES6 嚴格模式下,知足如下三個條件,尾調用再也不建立新的 stack frame ,而是重用當前 stack frame

  • 函數不是一個閉包。
  • 在函數內部,尾調用是最後一條語句。
  • 尾調用的結果做爲函數值返回。
示例:
'use strict';
function func(){
    //優化後
    return f();
}

而如下幾種狀況不會進行優化:

  • 當沒有做爲函數值返回,不會優化:
function func(){
    f(); 
}
  • 返回值後還須要作其餘操做,也不會優化:
function func(){
  return 1+f(); //返回值後還須要作其餘操做
};
  • 函數調用不在尾部,也不會優化:
function func(){
  const result = f(); 
  return result;
};
  • 調用的函數是一個閉包函數,也不會優化:
function func(){
  const a= 1;
  const f = () => a //這是一個閉包函數,函數 f 須要訪問局部變量a
  return f();
};

更多連接:https://www.9xkd.com/

相關文章
相關標籤/搜索