1. 程式人生 > >ES6 之 函式的擴充套件

ES6 之 函式的擴充套件

函式引數的預設值

    function log(x, y) {
      y = y || 'world'
      console.log(x + ' ' + y);
    }
    log('hello') // hello world
    log('hello','China') // hello China
    log('hello', '') // hello world
    /*
    * 如果 y 沒有賦值,指定預設值為world // log('hello') // hello world
    * 如果 y 有賦值,指定賦值  log('hello','China') // hello China
    * 如果 y 有賦值,但是為 boolean 值 false,則該賦值就不起作用了  log('hello', '') // hello world
    * 
*/

 

函式的length屬性

console.log((function (a) {}).length) // 1
console.log((function (a = 1) {}).length) // 0 
console.log((function (a, b = 1, c) {}).length) //1
console.log((function (a, b , c = 2) {}).length) // 2
// 返回沒有賦值形參的個數
// 如果設定了預設值的引數不是尾引數,那麼length屬性也不再計入後面的引數

 

箭頭函式

var f = v => v;
    
// 如果見箭頭函式不需要引數 或者 需要對個引數,就是用圓括號代表引數部分 var sum = (num1, num2) => num1 + num2 // 如果箭頭函式的程式碼塊部分多餘一條語句,就要使用大括號將其闊起來, // 並使用return語句返回 // 如果箭頭函式直接返回一個物件,必須在物件外面加上括號 var getTempItem = id => ({ id: id, name: "Temp"}) // 箭頭函式 注意事項 /* * 函式體內的this物件就是定義時所在的物件,而不是使用時所在的隊形 * 不可以當做建構函式 * 不可以使用arguments物件 * 不可以使用yield命令,因此箭頭函式態用作Generator函式 * 箭頭函式可以讓this指向固定化,這種形式非常有利於封裝回調函式 * 箭頭函式可以繫結this,大大減少了顯示繫結this物件的寫法(call,apply,bind)
*/

 

作用域

賦值的形參形成單獨的作用域

 

箭頭函式

《ES6標準入門》 第三版

箭頭函式有幾個使用注意點。
(1)函式體內的this物件,就是定義時所在的物件,而不是使用時所在的物件。
(2)不可以當作建構函式,也就是說,不可以使用new命令,否則會丟擲一個錯誤。
(3)不可以使用arguments物件,該物件在函式體內不存在。如果要用,可以用 rest 引數代替。
(4)不可以使用yield命令,因此箭頭函式不能用作 Generator 函式。
上面四點中,第一點尤其值得注意。this物件的指向是可變的,但是在箭頭函式中,它是固定的。

箭頭函式可以讓setTimeout裡面的this,繫結定義時所在的作用域,而不是指向執行時所在的作用域。

箭頭函式可以讓this指向固定化,這種特性很有利於封裝回調函式。

 

繫結this

箭頭函式可以繫結this物件,大大減少了顯式繫結this物件的寫法(call、apply、bind)。但是,箭頭函式並不適用於所有場合,所以現在有一個 提案,提出了“函式繫結”(function bind)運算子,用來取代call、apply、bind呼叫。
函式繫結運算子是並排的兩個冒號(::),雙冒號左邊是一個物件,右邊是一個函式。該運算子會自動將左邊的物件,作為上下文環境(即this對 象),繫結到右邊的函式上面。

如果雙冒號左邊為空,右邊是一個物件的方法,則等於將該方法繫結在該物件上面。

尾呼叫及優化

就是指某個函式的後一步是呼叫另一個函式。

函式呼叫會在記憶體形成一個“呼叫記錄”,又稱“呼叫幀”(call frame),儲存呼叫位置和內部變數等資訊。

如果在函式A的內部呼叫函式B,那 麼在A的呼叫幀上方,還會形成一個B的呼叫幀。

等到B執行結束,將結果返回到A,B的呼叫幀才會消失。如果函式B內部還呼叫函式C,那就還有一 個C的呼叫幀,

以此類推。所有的呼叫幀,就形成一個“呼叫棧”(call stack)。


尾呼叫由於是函式的後一步操作,所以不需要保留外層函式的呼叫幀,因為呼叫位置、內部變數等資訊都不會再用到了,只要直接用內層函式的呼叫 幀,取代外層函式的呼叫幀就可以了。

 

只保留內層函式的呼叫幀。如果所有函式都是尾呼叫,那麼完全可以做到每次執行時,呼叫幀只有 一項,這將大大節省記憶體。這就是“尾呼叫優化”的意義。
注意,只有不再用到外層函式的內部變數,內層函式的呼叫幀才會取代外層函式的呼叫幀,否則就無法進行“尾呼叫優化”。

尾遞迴及優化

函式呼叫自身,稱為遞迴。如果尾呼叫自身,就稱為尾遞迴。

遞迴非常耗費記憶體,因為需要同時儲存成千上百個呼叫幀,很容易發生“棧溢位”錯誤(stack overflow)。但對於尾遞迴來說,由於只存在一個呼叫幀, 所以永遠不會發生“棧溢位”錯誤。

ES6 中只要使用尾遞迴,就不會發生棧溢位,相對節省記憶體。