### 基礎語法
~~~js
(參數1, 參數2, …, 參數N) => { 函數聲明 }
//相當于:(參數1, 參數2, …, 參數N) =>{ return 表達式; }
(參數1, 參數2, …, 參數N) => 表達式(單一)
// 當只有一個參數時,圓括號是可選的:
(單一參數) => {函數聲明}
單一參數 => {函數聲明}
// 沒有參數的函數應該寫成一對圓括號。
() => {函數聲明}
~~~
### 高級語法
~~~js
//加括號的函數體返回對象字面表達式:
參數=> ({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
~~~
### 引入箭頭函數有兩個方面的作用:更簡短的函數并且不綁定`this`。
## 不綁定this
<span style="color:red;">
在箭頭函數出現之前,每個新定義的函數都有它自己的?this值(在構造函數的情況下是一個新對象,在嚴格模式的函數調用中為 undefined,如果該函數被作為“對象方法”調用則為基礎對象等)。`This`被證明是令人厭煩的面向對象風格的編程。</span>
~~~js
function Person() {
// Person() 構造函數定義 `this`作為它自己的實例.
this.age = 0;
setInterval(function growUp() {
// 在非嚴格模式, growUp()函數定義 `this`作為全局對象,
// 與在 Person()構造函數中定義的 `this`并不相同.
this.age++;
}, 1000);
}
var p = new Person();
~~~
ES5解決辦法
~~~js
function Person() {
var that = this;
that.age = 0;
setInterval(function growUp() {
// 回調引用的是`that`變量, 其值是預期的對象.
that.age++;
}, 1000);
}
~~~
<span style='color:red;'>箭頭函數不會創建自己的`this,它只會從自己的作用域鏈的上一層繼承this`。因此,在下面的代碼中,傳遞給`setInterval`的函數內的`this`與封閉函數中的`this`值相同:</span>
### 通過 call 或?apply 調用
由于箭頭函數沒有自己的this指針,通過?`call()`*?或*`apply()`?方法調用一個函數時,只能傳遞參數(不能綁定this---譯者注),他們的第一個參數會被忽略。(這種現象對于bind方法同樣成立---譯者注)
### <span style="color:red">箭頭函數不綁定Arguments對象</span>
因此,在本示例中,`arguments`只是引用了封閉作用域內的arguments:
~~~
var arguments = [1, 2, 3];
var arr = () => arguments[0];
arr(); // 1
function foo(n) {
var f = () => arguments[0] + n; // 隱式綁定 foo 函數的 arguments 對象. arguments[0] 是 n
return f();
}
foo(1); // 2
~~~
在大多數情況下,使用[剩余參數](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Rest_parameters)是相較使用`arguments`對象的更好選擇。
~~~js
function foo(arg) {
var f = (...args) => args[0];
return f(arg);
}
foo(1); // 1
function foo(arg1,arg2) {
var f = (...args) => args[1];
return f(arg1,arg2);
}
foo(1,2); //2
~~~
### <span style="color:red">### 像函數一樣使用箭頭函數</span>
箭頭函數表達式對非方法函數是最合適的。讓我們看看當我們試著把它們作為方法時發生了什么。
~~~js
'use strict';
var obj = {
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log( this.i, this)
}
}
obj.b();
// undefined
obj.c();
// 10, Object {...}
~~~
箭頭函數沒有定義this綁定。另一個涉及[`Object.defineProperty()`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty "Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 并返回這個對象。")的示例:
~~~js
'use strict';
var obj = {
a: 10
};
Object.defineProperty(obj, "b", {
get: () => {
console.log(this.a, typeof this.a, this);
return this.a+10;
// 代表全局對象 'Window', 因此 'this.a' 返回 'undefined'
}
});
obj.b; // undefined "undefined" Window {postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window, …}
~~~
### <span style="color:red">[使用?`new`?操作符](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions#%E4%BD%BF%E7%94%A8_new_%E6%93%8D%E4%BD%9C%E7%AC%A6)[](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions#%E4%BD%BF%E7%94%A8_new_%E6%93%8D%E4%BD%9C%E7%AC%A6)</span>
箭頭函數不能用作構造器,和`new`一起用會拋出錯誤。
~~~js
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor
~~~
### 箭頭函數沒有`prototype`屬性。
~~~js
var Foo = () => {};
console.log(Foo.prototype); // undefined
~~~
## 函數體
箭頭函數可以有一個“簡寫體”或常見的“塊體”。
在一個簡寫體中,只需要一個表達式,并附加一個隱式的返回值。在塊體中,必須使用明確的`return`語句。
~~~js
var func = x => x * x;
// 簡寫函數 省略return
var func = (x, y) => { return x + y; };
//常規編寫 明確的返回值
~~~
### 箭頭函數內定義的變量及其作用域
~~~js
// 常規寫法
var greeting = () => {let now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));}
greeting(); //"Good day."
console.log(now); // ReferenceError: now is not defined 標準的let作用域
// 參數括號內定義的變量是局部變量(默認參數)
var greeting = (now=new Date()) => "Good" + (now.getHours() > 17 ? " evening." : " day.");
greeting(); //"Good day."
console.log(now); // ReferenceError: now is not defined
// 對比:函數體內{}不使用var定義的變量是全局變量
var greeting = () => {now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));}
greeting(); //"Good day."
console.log(now); // Fri Dec 22 2017 10:01:00 GMT+0800 (中國標準時間)
// 對比:函數體內{} 用var定義的變量是局部變量
var greeting = () => {var now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));}
greeting(); //"Good day."
console.log(now); // ReferenceError: now is not defined
~~~