ES6-函式的擴充套件
1. 函式引數預設值
在ES5中我們想給函式的引數設定預設值通常是通過短路表示式來操作:
function log(x, y) { y = y || 'World'; console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello World
ES6則允許為函式的引數設定預設值,即直接寫在引數定義的後面。
function log(x, y = 'World') { console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello
2. rest引數
形式為“...變數名”,用於獲取函式的多餘引數。rest引數搭配的變數是一個數組,該變數將多餘的引數放入陣列中。注意,rest引數之後不能再有其他引數(即只能是最後一個引數),否則會報錯。
function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum; } add(2, 5, 3) // 10
3. 擴充套件運算子(spread)
是三個點(…)。它好比rest引數的逆運算,將一個數組轉為用逗號分隔的引數序列,該運算子主要用於函式呼叫。
function add(x, y) { return x + y; } var numbers = [4, 38]; add(...numbers) // 42
這裡在舉個例子,我們先從Math.max()函式說起,Math.max後面可以接任意個引數,最後返回所有引數中的最大值。比如
alert(Math.max(5,8)) //8 alert(Math.max(5,7,9,3,1,6)) //9
但是在很多情況下,我們需要找出陣列中最大的元素。
var arr=[5,7,9,1] alert(Math.max(arr)) // 這樣卻是不行的。一定要這樣寫 function getMax(arr){ var arrLen=arr.length; for(var i=0,ret=arr[0];i<arrLen;i++){ ret=Math.max(ret,arr[i]); } return ret; }
這樣寫麻煩而且低效。如果用 apply呢,看程式碼:
function getMax2(arr){ return Math.max.apply(null,arr); }
那如果使用ES6呢
function getMax3(arr){ return Math.max(...arr); } getMax3(arr) //9
4. 箭頭函式
在箭頭函數出現之前,每個新定義的函式都有它自己的 this
值(在建構函式的情況下是一個新物件,在嚴格模式的函式呼叫中為 undefined,如果該函式被作為“物件方法”呼叫則為基礎物件等),尋找This
的指向更是令人厭煩。所以在ES6引入了箭頭函式,其優勢更簡短的函式並且不繫結this。箭頭函式不會建立自己的
this,它只會從自己的作用域鏈的上一層繼承this。
至於什麼說是箭頭函式呢?因為他是由箭頭定義的啊,O(∩_∩)O。
(1) 如果箭頭函式不需要引數或需要多個引數,就使用一個圓括號代表引數部分
(2) 如果箭頭函式的程式碼塊部分多於一條語句,就要使用大括號將它們括起來,並且使用return語句返回。
箭頭函式的基本語法:
(引數1, 引數2, …, 引數N) => { 函式宣告 } //相當於:(引數1, 引數2, …, 引數N) =>{ return 表示式; } (引數1, 引數2, …, 引數N) => 表示式(單一) // 當只有一個引數時,圓括號是可選的: (單一引數) => {函式宣告} 單一引數 => {函式宣告}
v => v;
//上面的箭頭函式等同於:
function(v) { return v; };
// 沒有引數的函式應該寫成一對圓括號。 () => {函式宣告}
高階語法
//加括號的函式體返回物件字面表示式: 引數=> ({foo: bar}) //支援剩餘引數和預設引數 (引數1, 引數2, ...rest) => {函式宣告} (引數1 = 預設值1,引數2, …, 引數N = 預設值N) => {函式宣告} //同樣支援引數列表解構 let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f(); // 6
箭頭函式可以有一個“簡寫體”或常見的“塊體”。
在一個簡寫體中,只需要一個表示式,並附加一個隱式的返回值。在塊體中,必須使用明確的return
語句。
var func = x => x * x; // 簡寫函式 省略return var func = (x, y) => { return x + y; }; //常規編寫 明確的返回值
返回物件字面量節
記住用params => {object:literal}
這種簡單的語法返回物件字面量是行不通的。
var func = () => { foo: 1 }; // Calling func() returns undefined! var func = () => { foo: function() {} }; // SyntaxError: function statement requires a name
這是因為花括號({}
)裡面的程式碼被解析為一系列語句(即 foo
被認為是一個標籤,而非物件字面量的組成部分)。
所以,記得用圓括號把物件字面量包起來:
var func = () => ({foo: 1});
箭頭函式內定義的變數及其作用域
this指向問題
注意:
(1)函式體內的this物件,就是定義時所在的物件,而不是使用時所在的物件。通過 call 或 apply 呼叫由於 箭頭函式沒有自己的this指標,通過 call()
或 apply()
方法改變this指向。
上面程式碼中,setTimeout的引數是一個箭頭函式,這個箭頭函式的定義生效是在foo函式生成時,而它的真正執行要等到100毫秒後。如果是普通函式,執行時this應該指向全域性物件window,這時應該輸出21。但是,箭頭函式導致this總是指向函式定義生效時所在的物件(本例是{id: 42}),所以輸出的是42。即箭頭函式可以讓setTimeout裡面的this,繫結定義時所在的作用域,而不是指向執行時所在的作用域。
(2)不可以當作建構函式,也就是說,不可以使用new命令,否則會丟擲一個錯誤。