箭頭函數是ES6
中新增的特性,因其在語言上的簡潔性,相信不少人都很是喜歡使用它。對於初學者來講,對於箭頭函數的熟練使用與深入理解須要一個過程。本文總結一下普通函數與箭頭函數的區別,但願可以使這一過程加速。es6
ES6
容許使用「箭頭」(=>
)定義函數。具體的定義,能夠看下面的例子。面試
var f = v => v
// 等同於
var f = function (v) {
return v
}
複製代碼
能夠看出,定義箭頭函在數語法上要比普通函數簡潔得多。箭頭函數省去了function
關鍵字,採用箭頭=>
來定義函數。函數的參數放在=>
前面的括號中,函數體跟在=>
後的花括號中。數組
一、若是箭頭函數沒有參數,直接寫一個空括號便可。bash
var f = () => 5
// 等同於
var f = function () { return 5 }
複製代碼
二、若是箭頭函數的參數只有一個,也能夠省去包裹參數的括號。app
var f = v => v
// 等同於
var f = function (v) {
return v
}
複製代碼
三、若是箭頭函數有多個參數,將參數依次用逗號(,)
分隔,包裹在括號中便可。函數
var sum = (num1, num2) => num1 + num2
// 等同於
var sum = function(num1, num2) {
return num1 + num2
}
複製代碼
一、若是箭頭函數的函數體只有一句代碼,就是簡單返回某個變量或者返回一個簡單的JS表達式,能夠省去函數體的大括號{ }
。學習
var f = v => v
複製代碼
二、若是箭頭函數的函數體只有一句代碼,就是返回一個對象,要使用()
ui
// 用小括號包裹要返回的對象,不報錯
let getTempItem = id => ({ id: id, name: "Temp" });
// 但毫不能這樣寫,會報錯。
// 由於對象的大括號會被解釋爲函數體的大括號
let getTempItem = id => { id: id, name: "Temp" };
複製代碼
三、若是箭頭函數的函數體只有一條語句而且不須要返回值(最多見是調用一個函數),能夠給這條語句前面加一個void
關鍵字this
let fn = () => void doesNotReturn()
複製代碼
一、箭頭函數能夠與變量解構結合使用。能夠用在請求接口時,只接受的返回數據中須要的字段。spa
const full = ({ first, last }) => first + ' ' + last;
// 等同於
function full(person) {
return person.first + ' ' + person.last;
}
複製代碼
二、箭頭函數能夠簡化回調函數。
// 正常函數寫法
[1,2,3].map(function (x) {
return x * x;
});
// 箭頭函數寫法
[1,2,3].map(x => x * x);
複製代碼
三、rest
參數與箭頭函數結合簡化開發。
const numbers = (...nums) => nums;
numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]
const headAndTail = (head, ...tail) => [head, tail];
headAndTail(1, 2, 3, 4, 5)
// [1,[2,3,4,5]]
複製代碼
一、箭頭函數沒有原型prototype
let a = () =>{};
console.log(a.prototype); // undefined
複製代碼
二、箭頭函數不會建立本身的this
箭頭函數不會建立本身的
this
,因此它沒有本身的this
,它只會從本身的做用域鏈的上一層繼承this
。
箭頭函數沒有本身的this
,它會捕獲本身在定義時(注意,是定義時,不是調用時)所處的外層執行環境的this
,並繼承這個this
值。因此,箭頭函數中this
的指向在它被定義的時候就已經肯定了,以後永遠不會改變。
var id = 'Global';
function fun1() {
// setTimeout中使用普通函數
setTimeout(function(){
console.log(this.id);
}, 2000);
}
function fun2() {
// setTimeout中使用箭頭函數
setTimeout(() => {
console.log(this.id);
}, 2000)
}
fun1.call({id: 'Obj'}); // 'Global'
fun2.call({id: 'Obj'}); // 'Obj'
複製代碼
三、不能修改箭頭函數的this
指向
因爲箭頭函數的this
定義時就已經肯定且永遠不會改變。因此使用這些方法永遠也改變不了箭頭函數this
的指向,雖然這麼作代碼不會報錯。
var id = 'Global';
// 箭頭函數定義在全局做用域
let fun1 = () => {
console.log(this.id)
};
fun1(); // 'Global'
// this的指向不會改變,永遠指向Window對象
fun1.call({id: 'Obj'}); // 'Global'
fun1.apply({id: 'Obj'}); // 'Global'
fun1.bind({id: 'Obj'})(); // 'Global'
複製代碼
四、箭頭函數不能做爲構造函數使用
咱們先了解普通函數new構造函數的步驟:
this
指向該對象。this
。可是箭頭函數沒有本身的this
,它的this
實際上是繼承了外層執行環境中的this
,且this
指向永遠不會隨在哪裏調用、被誰調用而改變,因此箭頭函數不能做爲構造函數使用,或者說構造函數不能定義成箭頭函數,不然用new
調用時會報錯!
let Fun = (name, age) => {
this.name = name;
this.age = age;
};
// 報錯
let p = new Fun('cao', 24)
複製代碼
五、箭頭函數沒有本身的arguments
箭頭函數沒有本身的arguments
對象。在箭頭函數中訪問arguments
實際上得到的是外層局部(函數)執行環境中的值。
除了arguments、this如下兩個變量在箭頭函數之中也是不存在的,指向外層函數的對應變量:super、new.target。
(1) 箭頭函數的this
指向全局對象,會報arguments
未聲明的錯誤。
let b = () => {
console.log(arguments);
};
b(1, 2, 3, 4); // Uncaught ReferenceError: arguments is not defined
複製代碼
(2) 箭頭函數的this
若是指向普通函數,它的argumens
繼承於該普通函數。
function bar() {
console.log(arguments); // ['bar']
bb('bb');
function bb() {
console.log(arguments); // ["bb"]
let a = () => {
console.log(arguments); // ["bb"]
};
a('箭頭函數的參數'); // this指向bb
}
}
bar('bar');
複製代碼
能夠在箭頭函數中使用rest參數代替arguments對象,來訪問箭頭函數的參數列表!!
ES6
引入 rest
參數(形式爲...變量名),用於獲取函數的多餘參數,這樣就不須要使用arguments
對象了。rest
參數搭配的變量是一個數組,該變量將多餘的參數放入數組中。
let a = (a, ...bcd) => {
console.log(a, bcd); // 1 [2, 3, 4]
};
a(1, 2, 3, 4);
複製代碼
上面的例子除了第一個參數肯定外,用一個變量接收其餘的變量。固然你也可使用一個變量接收全部的參數。
一、rest
參數必須是最後一個參數,不然會報錯。
// 報錯
function f(a, ...b, c) {
// ...
}
複製代碼
二、rest
參數沒有函數的length
屬性。
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 1
複製代碼
六、箭頭函數不支持重命名函數參數,普通函數的函數參數支持重命名
function func1(a, a) {
console.log(a, arguments); // 2 [1,2]
}
var func2 = (a,a) => {
console.log(a); // 報錯:在此上下文中不容許重複參數名稱
};
func1(1, 2); func2(1, 2);
複製代碼
七、語法更加簡潔、清晰
從上面的基本語法示例中能夠看出,箭頭函數的定義要比普通函數定義簡潔、清晰得多,很快捷。
本段摘自阮一峯ES6入門瞭解詳情可點擊參考。
一、定義對象的方法,且該方法內部包括this。
const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
複製代碼
上面代碼中,cat.jumps()
方法是一個箭頭函數,這是錯誤的。調用cat.jumps()
時,若是是普通函數,該方法內部的this
指向cat
;若是寫成上面那樣的箭頭函數,使得this
指向全局對象,所以不會獲得預期結果。這是由於對象不構成單獨的做用域,致使jumps
箭頭函數定義時的做用域就是全局做用域。
二、須要動態this的時候,不該使用箭頭函數。
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
複製代碼
上面代碼運行時,點擊按鈕會報錯,由於button
的監聽函數是一個箭頭函數,致使裏面的this
就是全局對象。若是改爲普通函數,this
就會動態指向被點擊的按鈕對象。
(,)
分隔,包裹在括號中便可。prototype
。this
。this
指向。arguments
。(super、new.target
也沒有)。this
意外指向和代碼的可讀性。注意事項:
rest
參數須要放在最後。箭頭函數是ES6重點知識了,不論是在面試上,仍是在平時開發中,都是常常會被問道且使用到的知識。所以,咱們應該系統的去掌握和深刻理解它。但願還不是很熟練的童鞋要抓緊時間學習,它值得咱們你們花時間去整理和總結。