箭頭函數是指經過=>語法定義的函數。JS編程中常常定義一些短小的匿名函數,使用箭頭函數語法可以使得這類函數的定義更加簡潔。javascript
// ES3/5方式 var fun1 = function(x, y) { return x + y; } var arr1 = [1,2,3].map(function(item){ return item * item; }) // 箭頭函數方式 var fun2 = (x, y) => x + y; var arr2 = [1,2,3].map((item) => item * item)
少些了很多代碼,看着也簡潔許多,有木有。html
通常的語法格式:java
(param1, param2, …, paramN) => { 語句 }
注意參數部分和箭頭=>之間不能換行,如:es6
// 正確 var add1 = (x, y) => x + y; // 正確 var add2 = (x, y) => x + y; // 正確(=>後面不會自動插入分號的) var add3 = (x, y) => x + y; // 語法錯誤 Uncaught SyntaxError: Unexpected token => var add4 = (x, y) => x + y; // 語法錯誤 Uncaught SyntaxError: Unexpected token => var add5= x => x + 2;
上例中add4定義會報錯,緣由在解析的時候(x, y)後面會自動插入分號,因此當解析=>時就報錯了。編程
若是花括號裏只包含一個return語句,則能夠簡寫爲:閉包
(param1, param2, …, paramN) => 表達式 // 等價於 => { return 表達式; }
由於對象字面量也是用花括號表示的,因此當表達式是個對象字面量時須要用括號包住:app
var a = p => ({a: p}) // 不能寫成:p => {a: p}
若是有且只有一個形參,則能夠省略括號,簡寫爲:函數
param => {語句} // 等價於 (param) => {語句}
如上例中的fun1定義:學習
var fun1 = (x, y) => x + y; // 等價於 var fun1 = (x, y) => { return x + y; }
箭頭函數不單單更方便定義匿名函數,它還具備一些特性,這些使得箭頭函數在使用上也更方便。
箭頭函數通常定義在一個函數內部,箭頭函數的函數體內是能夠訪問外部函數定義的局部變量的(閉包),可是外部函數還有兩個特殊的變量:this和arguments。由於每一個函數都具備本身的this和arguments變量,因此當內部函數訪問外部函數這兩個變量時,咱們通常採用這種方式:this
var outer = { name: 'outer', say: function() { var _arguments = arguments, // 先把arguments賦值給局部變量_arguments _this = this; // 先把this賦值給局部變量_this function inner() { console.log(arguments.length); // 內部函數的arguments console.log(_arguments.length); // 經過局部變量_arguments訪問外部函數的arguments變量 console.log(this.name); // 內部函數的this console.log(_this.name); // 經過局部變量_this訪問外部函數的this變量 } return inner; } }
可是箭頭函數體能夠直接訪問外部函數的this和arguments變量!!!逆天啊。
箭頭函數體內this變量指向外部函數的this。如上例能夠寫爲:
var outer = { name: 'outer', say: function() { return () => { console.log(this.name); } // 外部函數outer的this, } }
而且經過call,apply,bind函數也是沒法修改箭頭函數的this變量的。
var outer = { name: 'outer', say: function() { var inner = () => { console.log(this.name); } // 依舊外部函數outer的this, return inner.bind({name: 'inner'}) // } }
箭頭函數並非真的不具備本身的this變量,只是它從新修改this變量的值。
var outer = { name: 'outer', say: function() { return () => { console.log(this.name); } // 外部函數outer的this, } } // 等價於: var outer = { name: 'outer', say: function say() { var _this = this; // 定義個局部變量_this return function () { this = _this; // 修改內部的this console.log(this.name); }; } };
因此這樣call,apply,bind也就沒法修改箭頭函數的this值的。
跟this變量相似箭頭函數也「不具備本身的arguments變量」,原理跟this相似。
總結一句話:箭頭函數是爲了特殊的使用場景(即更方便的定義和使用匿名函數),它的這些特性也是爲了方便其使用。
對箭頭函數使用new操做符會拋TypeError異常。
var A = () => {} var a = new A(); //拋異常 Uncaught TypeError: A is not a constructor
即箭頭函數不能做爲構造函數,其也不具備prototype屬性。緣由應該是其內部的this變量被重寫了,不能做爲構造函數理所固然。可是箭頭函數也是函數:
var a = () => {}; console.log(a instanceof Function); // true
總結一句話:箭頭函數是不能做爲構造函數的特殊函數。
箭頭函數=>不是運算符,當箭頭函數做爲右值跟其餘運算符一塊兒運算操做時其具備特殊的解析順序
function func(callback) { // 通常函數方式 callback = callback || function() {} // 沒問題 // 報錯了,語法錯誤:Uncaught SyntaxError: Unexpected token ) callback = callback || () => {}; // 這樣寫就對了 callback = callback || (() => {}); }
總結一句話:箭頭函數雖然不是運算符,但其寫法和解析有點像運算符的操做。當箭頭函數做爲右值參與其餘運算符的運算時記得加上括號。
箭頭函數"沒有本身的this",因此它不適用那些須要使用本身this的場景(如成員方法,事件回調函數等)
// 成員方法 var outer = { name: 'outer', say: () => { // 這裏的this不是outer,可是咱們指望在成員方法的this應該指向對象自己 console.log(this.name); } } // 事件處理函數 document.getElementById('test').onclick = function() { console.log(this); // 這裏的this不是觸發事件的DOM對象 }
總結一句話:箭頭函數雖然寫起了比較爽,但不能濫用,它是有特殊應用場景的。要懂得何時不應用。