ES6學習歷程 14 — 箭頭函示
ES6 Arrow functions
ES6為函式表達式提供更方便簡潔的書寫方式,就是使用「箭頭」(=>)定義函式。
來看個範例:
// add() 是函式表達式,這是我們熟知的書寫方式let add = function(x, y) { return x + y;}console.log(add(10,20)); // 30
// 以下 add() 是使用箭頭函式的函式表達式let add = (x, y) => x + y;console.log(add(10,20)); // 30;
// 也可以這樣寫let add = (x, y) => { return x + y; };// 如果箭頭函式不需要參數,就使用一個圓括號:let add = () => ({ id: 001, name: "Tim" });
多個參數
如果箭頭函式有兩個或以上的參數,就要使用下面的書寫方式:
(p1, p2, …, pn) => expression;
上述也等同於這樣寫:
(p1, p2, …, pn) => { return expression; }
使用範例:
let numbers = [4,2,6];numbers.sort(function(a, b){ return b — a;});console.log(numbers); // [6,4,2]
上述範例可以用箭頭函式這樣寫,如下:
let numbers = [4,2,6];numbers.sort((a, b) => b — a);console.log(numbers); // [6,4,2]
不允許在定義參數和箭頭間換行
let multiply = (x, y)=> x * y;// SyntaxError
但是,如果在箭頭後換行就沒有問題:
let multiply = (x, y) =>x * y;// work
這樣也沒有問題:
let multiply = (x,y) =>x * y;// work
箭頭函式與物件語法
某函式回傳物件,JS使用方法是這樣:
let setColor = function (color) { return {value: color}};let backgroundColor = setColor('Red');console.log(backgroundColor.value); // "Red"
如果換成箭頭函式的話:
let setColor = color => { value: color }; // NaN,會造成錯誤let setColor = color => ({ value: color });
// 因為javascript無法分辨這是區塊還是物件而出現錯誤,所以需要在物件外面加上括號 ( ) 才能正常運行let backgroundColor = setColor('Red');console.log(backgroundColor.value); // "Red"
箭頭函式與this
在JS中,的函式會定義自己的this。看範例:
function Car() { this.speed = 0; this.speedUp = function (speed) { this.speed = speed; setTimeout(function () { console.log(this.speed); // undefined }, 1000); };}let car = new Car();car.speedUp(50);
在setTimeOut() 中的this.speed 為 undefined。這是因為,在setTimeOut() 的匿名函式中的this是setTimeOut()自己定義的this,跟speedUp() 定義的this不是同一個。
如果用箭頭函式的話,就沒有這個問題:
function Car() { this.speed = 0; this.speedUp = function (speed) { this.speed = speed; setTimeout(() => console.log(this.speed), 1000); };}let car = new Car();car.speedUp(50); // 50;
請問下面的範例中有幾個this呢?
function foo() { return () => { return () => { return () => { console.log(‘id:’, this.id); }; }; };}var f = foo.call({id: 1});var t1 = f.call({id: 2})()(); // id: 1var t2 = f().call({id: 3})(); // id: 1var t3 = f()().call({id: 4}); // id: 1
上面的範例中,只有一個this,就是函式foo的this,所以t1、t2、t3都輸出同樣的結果。因為所有內層函式都是箭頭函式,都沒有自己的this,他們的this都是最外層的foo函式的this。
除了this,以下三個變數在箭頭函式中也是不存在的,都指向最外層的變數:arguments、super、new.target。
function foo() { setTimeout(() => { console.log('args:', arguments); }, 100);}foo(2, 4, 6, 8)// args: [2, 4, 6, 8]
上面範例中,箭頭函式內部的變數arguments,其實是foo的arguments變數。
另外,由於箭頭函式沒有自己的this,所以也就不能使用call()、apply()、bind()這些方法來改變this的指向。
(function() { return [(() => this.x).bind({ x: 'inner' })()];}).call({ x: 'outer' });// ['outer']
在上數程式碼中,箭頭函示没有自己的this,所以bind方法無效,内部的this指向外部的this。