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

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命令,否則會丟擲一個錯誤。