ES6-箭头函数
一、概述
箭頭函數是指通過=>語法定義的函數。JS編程中經常定義一些短小的匿名函數,使用箭頭函數語法可使得這類函數的定義更加簡潔。
// 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)少些了不少代碼,看著也簡潔許多,有木有。
二、語法
-
一般的語法格式:
(param1, param2, …, paramN) => { 語句 }注意參數部分和箭頭=>之間不能換行,如:
// 正確 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 表達式; }因為對象字面量也是用花括號表示的,所以當表達式是個對象字面量時需要用括號包住:
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和arguments變量!!!逆天啊。
3.1 箭頭函數“不具有自己的this變量”
1 特性語法
箭頭函數體內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'}) //} }2 特性原理
箭頭函數并不是真的不具有自己的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; // 定義個局部變量_thisreturn function () {this = _this; // 修改內部的thisconsole.log(this.name);};} };所以這樣call,apply,bind也就無法修改箭頭函數的this值的。
3.2 箭頭函數“不具有自己的arguments變量”
跟this變量類似箭頭函數也“不具有自己的arguments變量”,原理跟this類似。
總結一句話:箭頭函數是為了特殊的使用場景(即更方便的定義和使用匿名函數),它的這些特性也是為了方便其使用。
四、使用限制
4.1 不能用new 操作符
對箭頭函數使用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總結一句話:箭頭函數是不能作為構造函數的特殊函數。
4.2 跟其他運算符一起用
箭頭函數=>不是運算符,當箭頭函數作為右值跟其他運算符一起運算操作時其具有特殊的解析順序
function func(callback) {// 一般函數方式callback = callback || function() {} // 沒問題// 報錯了,語法錯誤:Uncaught SyntaxError: Unexpected token )callback = callback || () => {};// 這樣寫就對了callback = callback || (() => {}); }總結一句話:箭頭函數雖然不是運算符,但其寫法和解析有點像運算符的操作。當箭頭函數作為右值參與其他運算符的運算時記得加上括號。
4.3 需要使用自己this的函數
箭頭函數"沒有自己的this",所以它不適用那些需要使用自己this的場景(如成員方法,事件回調函數等)
// 成員方法 var outer = {name: 'outer',say: () => { // 這里的this不是outer,但是我們期望在成員方法的this應該指向對象本身console.log(this.name); } }// 事件處理函數 document.getElementById('test').onclick = function() {console.log(this); // 這里的this不是觸發事件的DOM對象 }總結一句話:箭頭函數雖然寫起了比較爽,但不能濫用,它是有特殊應用場景的。要懂得什么時候不該用。
參考
總結
- 上一篇: 刺激战场国际版在哪下
- 下一篇: 阿里资深技术专家:谁说程序员是吃“青春饭