前言
箭頭函數(shù)是ES6
中新增的特性过蹂,因其在語言上的簡潔性,相信很多人都非常喜歡使用它。對于初學(xué)者來說殿怜,對于箭頭函數(shù)的熟練使用與深刻理解需要一個過程。本文總結(jié)一下普通函數(shù)與箭頭函數(shù)的區(qū)別曙砂,希望能夠使這一過程加速头谜。
基本語法
ES6
允許使用“箭頭”(=>
)定義函數(shù)。具體的定義鸠澈,可以看下面的例子柱告。
var f = v => v
// 等同于
var f = function (v) {
return v
}
可以看出,定義箭頭函在數(shù)語法上要比普通函數(shù)簡潔得多笑陈。箭頭函數(shù)省去了function
關(guān)鍵字际度,采用箭頭=>
來定義函數(shù)。函數(shù)的參數(shù)放在=>
前面的括號中新锈,函數(shù)體跟在=>
后的花括號中甲脏。
箭頭函數(shù)的參數(shù)
1、如果箭頭函數(shù)沒有參數(shù)妹笆,直接寫一個空括號即可块请。
var f = () => 5
// 等同于
var f = function () { return 5 }
2、如果箭頭函數(shù)的參數(shù)只有一個拳缠,也可以省去包裹參數(shù)的括號墩新。
var f = v => v
// 等同于
var f = function (v) {
return v
}
3、如果箭頭函數(shù)有多個參數(shù)窟坐,將參數(shù)依次用逗號(,)
分隔海渊,包裹在括號中即可绵疲。
var sum = (num1, num2) => num1 + num2
// 等同于
var sum = function(num1, num2) {
return num1 + num2
}
箭頭函數(shù)的函數(shù)體
1、如果箭頭函數(shù)的函數(shù)體只有一句代碼臣疑,就是簡單返回某個變量或者返回一個簡單的JS表達式盔憨,可以省去函數(shù)體的大括號{ }
。
var f = v => v
2讯沈、如果箭頭函數(shù)的函數(shù)體只有一句代碼郁岩,就是返回一個對象,要使用()
// 用小括號包裹要返回的對象缺狠,不報錯
let getTempItem = id => ({ id: id, name: "Temp" });
// 但絕不能這樣寫问慎,會報錯。
// 因為對象的大括號會被解釋為函數(shù)體的大括號
let getTempItem = id => { id: id, name: "Temp" };
3挤茄、如果箭頭函數(shù)的函數(shù)體只有一條語句并且不需要返回值(最常見是調(diào)用一個函數(shù))如叼,可以給這條語句前面加一個void
關(guān)鍵字
let fn = () => void doesNotReturn()
箭頭函數(shù)實際使用場景
1、箭頭函數(shù)可以與變量解構(gòu)結(jié)合使用穷劈×。可以用在請求接口時,只接受的返回數(shù)據(jù)中需要的字段囚衔。
const full = ({ first, last }) => first + ' ' + last;
// 等同于
function full(person) {
return person.first + ' ' + person.last;
}
2挖腰、箭頭函數(shù)可以簡化回調(diào)函數(shù)雕沿。
// 正常函數(shù)寫法
[1,2,3].map(function (x) {
return x * x;
});
// 箭頭函數(shù)寫法
[1,2,3].map(x => x * x);
3练湿、rest
參數(shù)與箭頭函數(shù)結(jié)合簡化開發(fā)。
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]]
箭頭函數(shù)與普通函數(shù)的區(qū)別
箭頭函數(shù)中的this指向
1审轮、箭頭函數(shù)沒有原型prototype
let a = () =>{};
console.log(a.prototype); // undefined
2肥哎、箭頭函數(shù)不會創(chuàng)建自己的this
箭頭函數(shù)不會創(chuàng)建自己的
this
,所以它沒有自己的this
疾渣,它只會從自己的作用域鏈的上一層繼承this
篡诽。
箭頭函數(shù)沒有自己的this
,它會捕獲自己在定義時(注意榴捡,是定義時杈女,不是調(diào)用時)所處的外層執(zhí)行環(huán)境的this
,并繼承這個this
值吊圾。所以达椰,箭頭函數(shù)中this
的指向在它被定義的時候就已經(jīng)確定了,之后永遠(yuǎn)不會改變项乒。
var id = 'Global';
function fun1() {
// setTimeout中使用普通函數(shù)
setTimeout(function(){
console.log(this.id);
}, 2000);
}
function fun2() {
// setTimeout中使用箭頭函數(shù)
setTimeout(() => {
console.log(this.id);
}, 2000)
}
fun1.call({id: 'Obj'}); // 'Global'
fun2.call({id: 'Obj'}); // 'Obj'
3啰劲、不能修改箭頭函數(shù)的this
指向
由于箭頭函數(shù)的this
定義時就已經(jīng)確定且永遠(yuǎn)不會改變。所以使用這些方法永遠(yuǎn)也改變不了箭頭函數(shù)this
的指向檀何,雖然這么做代碼不會報錯蝇裤。
var id = 'Global';
// 箭頭函數(shù)定義在全局作用域
let fun1 = () => {
console.log(this.id)
};
fun1(); // 'Global'
// this的指向不會改變廷支,永遠(yuǎn)指向Window對象
fun1.call({id: 'Obj'}); // 'Global'
fun1.apply({id: 'Obj'}); // 'Global'
fun1.bind({id: 'Obj'})(); // 'Global'
4、箭頭函數(shù)不能作為構(gòu)造函數(shù)使用
我們先了解普通函數(shù)new構(gòu)造函數(shù)的步驟:
- ``JS```內(nèi)部首先會先生成一個對象栓辜。
- 再把函數(shù)中的
this
指向該對象恋拍。 - 然后執(zhí)行構(gòu)造函數(shù)中的語句。
- 最后隱式的返回
this
藕甩。
但是箭頭函數(shù)沒有自己的this
芝囤,它的this
其實是繼承了外層執(zhí)行環(huán)境中的this
,且this
指向永遠(yuǎn)不會隨在哪里調(diào)用辛萍、被誰調(diào)用而改變悯姊,所以箭頭函數(shù)不能作為構(gòu)造函數(shù)使用,或者說構(gòu)造函數(shù)不能定義成箭頭函數(shù)贩毕,否則用new
調(diào)用時會報錯悯许!
let Fun = (name, age) => {
this.name = name;
this.age = age;
};
// 報錯
let p = new Fun('cao', 24)
5、箭頭函數(shù)沒有自己的arguments
箭頭函數(shù)沒有自己的arguments
對象辉阶。在箭頭函數(shù)中訪問arguments
實際上獲得的是外層局部(函數(shù))執(zhí)行環(huán)境中的值先壕。
除了arguments、this以下兩個變量在箭頭函數(shù)之中也是不存在的谆甜,指向外層函數(shù)的對應(yīng)變量:super垃僚、new.target。
(1) 箭頭函數(shù)的this
指向全局對象规辱,會報arguments
未聲明的錯誤谆棺。
let b = () => {
console.log(arguments);
};
b(1, 2, 3, 4); // Uncaught ReferenceError: arguments is not defined
(2) 箭頭函數(shù)的this
如果指向普通函數(shù),它的argumens
繼承于該普通函數(shù)。
function bar() {
console.log(arguments); // ['bar']
bb('bb');
function bb() {
console.log(arguments); // ["bb"]
let a = () => {
console.log(arguments); // ["bb"]
};
a('箭頭函數(shù)的參數(shù)'); // this指向bb
}
}
bar('bar');
可以在箭頭函數(shù)中使用rest參數(shù)代替arguments對象罕袋,來訪問箭頭函數(shù)的參數(shù)列表8氖纭!
rest參數(shù)獲取參數(shù)列表
ES6
引入 rest
參數(shù)(形式為...變量名)浴讯,用于獲取函數(shù)的多余參數(shù)朵夏,這樣就不需要使用arguments
對象了。rest
參數(shù)搭配的變量是一個數(shù)組榆纽,該變量將多余的參數(shù)放入數(shù)組中仰猖。
let a = (a, ...bcd) => {
console.log(a, bcd); // 1 [2, 3, 4]
};
a(1, 2, 3, 4);
上面的例子除了第一個參數(shù)確定外,用一個變量接收其他的變量奈籽。當(dāng)然你也可以使用一個變量接收所有的參數(shù)饥侵。
rest參數(shù)需要注意的點
1、rest
參數(shù)必須是最后一個參數(shù)唠摹,否則會報錯爆捞。
// 報錯
function f(a, ...b, c) {
// ...
}
2、rest
參數(shù)沒有函數(shù)的length
屬性勾拉。
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 1
6煮甥、箭頭函數(shù)不支持重命名函數(shù)參數(shù),普通函數(shù)的函數(shù)參數(shù)支持重命名
function func1(a, a) {
console.log(a, arguments); // 2 [1,2]
}
var func2 = (a,a) => {
console.log(a); // 報錯:在此上下文中不允許重復(fù)參數(shù)名稱
};
func1(1, 2); func2(1, 2);
7盗温、語法更加簡潔、清晰
從上面的基本語法示例中可以看出成肘,箭頭函數(shù)的定義要比普通函數(shù)定義簡潔卖局、清晰得多,很快捷双霍。
箭頭函數(shù)的不適用場景
本段摘自阮一峰ES6入門了解詳情可點擊參考砚偶。
1、定義對象的方法洒闸,且該方法內(nèi)部包括this染坯。
const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
上面代碼中,cat.jumps()
方法是一個箭頭函數(shù)丘逸,這是錯誤的单鹿。調(diào)用cat.jumps()
時,如果是普通函數(shù)深纲,該方法內(nèi)部的this
指向cat
仲锄;如果寫成上面那樣的箭頭函數(shù),使得this
指向全局對象湃鹊,因此不會得到預(yù)期結(jié)果儒喊。這是因為對象不構(gòu)成單獨的作用域,導(dǎo)致jumps
箭頭函數(shù)定義時的作用域就是全局作用域币呵。
2怀愧、需要動態(tài)this的時候,不應(yīng)使用箭頭函數(shù)富雅。
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
上面代碼運行時掸驱,點擊按鈕會報錯肛搬,因為button
的監(jiān)聽函數(shù)是一個箭頭函數(shù)没佑,導(dǎo)致里面的this
就是全局對象。如果改成普通函數(shù)温赔,this
就會動態(tài)指向被點擊的按鈕對象蛤奢。
本章內(nèi)容小結(jié)
箭頭函數(shù)的使用
- 箭頭函數(shù)可以與變量解構(gòu)結(jié)合使用√赵簦可以用在請求接口時啤贩,只接受的返回數(shù)據(jù)中需要的字段。
- 箭頭函數(shù)可以簡化回調(diào)函數(shù)拜秧。
- 如果箭頭函數(shù)有多個參數(shù)痹屹,將參數(shù)依次用逗號
(,)
分隔,包裹在括號中即可枉氮。
箭頭函數(shù)與普通函數(shù)的區(qū)別
- 箭頭函數(shù)沒有原型
prototype
志衍。 - 箭頭函數(shù)不會創(chuàng)建自己的
this
暖庄。 - 不能修改箭頭函數(shù)的
this
指向。 - 箭頭函數(shù)不能作為構(gòu)造函數(shù)使用楼肪。
- 箭頭函數(shù)沒有自己的
arguments
培廓。(super、new.target
也沒有)春叫。 - 箭頭函數(shù)不支持重命名函數(shù)參數(shù),普通函數(shù)的函數(shù)參數(shù)支持重命名肩钠。
- 語法更加簡潔、清晰暂殖。
箭頭函數(shù)不適用場景
- 箭頭函數(shù)的
this
意外指向和代碼的可讀性价匠。
注意事項:
- 箭頭函數(shù)一條語句返回對象字面量,需要加括號呛每。
- 箭頭函數(shù)在參數(shù)和箭頭之間不能換行霞怀。
- 箭頭函數(shù)的
rest
參數(shù)需要放在最后。
參考文章
總結(jié)
箭頭函數(shù)是ES6重點知識了毙石,不管是在面試上,還是在平時開發(fā)中颓遏,都是經(jīng)常會被問道且使用到的知識徐矩。因此,我們應(yīng)該系統(tǒng)的去掌握和深入理解它叁幢。希望還不是很熟練的童鞋要抓緊時間學(xué)習(xí)滤灯,它值得我們大家花時間去整理和總結(jié)。