函數的擴展咱們能夠從三個方面來了解與認識:數組
在 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
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
屬性,能夠用於返回該函數的函數名。內存
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); }
函數 f1
和 f2
都屬於尾調用,由於這兩個函數調用都是函數 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(); };