1. 語法
按常規(guī)語法定義函數(shù):
function funcName(params) {
? ? return params + 2;
}
funcName(2);
該函數(shù)改成箭頭函數(shù):
var funcName = params => params + 2;
funcName(2);
我們來深入了解箭頭函數(shù)的語法:
parameters => {
? ? statements;
};
如果沒有參數(shù),那么可以進一步簡化:
() => {
? ? statements;
};
如果只有一個參數(shù)煌往,可以省略括號:
parameters => {
? ? statements;
};
如果函數(shù)體只有一句返回值,可以省略大括號和return
parameters => true;
等價于:
parameters => { return true;};
2. 箭頭函數(shù)和普通函數(shù)的區(qū)別
(1) 沒有this
箭頭函數(shù)沒有this藤树,需要通過查找作用域鏈來確定this的值。因此如果箭頭函數(shù)被非箭頭函數(shù)包裹栋烤,this綁定的就是最近一層非箭頭函數(shù)的this.
下面的例子是經(jīng)常遇到的:
var obj = {
? ? birth: 1990,
? ? getAge: function () {
? ? ? ? var b = this.birth; // 1990
? ? ? ? var fn = function () {
console.log(this); // this指向的是window或者undefined
? ? ? ? ? ? return new Date().getFullYear() - this.birth;
? ? ? ? };
? ? ? ? return fn();
? ? }
};
obj.getAge(); //NaN
上面的輸出結(jié)果是NaN历帚,因為fn是函數(shù)表達式,會有一個this指向它声邦,不能拿到外層函數(shù)的this,而fn沒有birth屬性摆舟,所以this.birth是undefined亥曹,因此輸出結(jié)果是NaN。
要修復(fù)這個問題恨诱,可以把外層的this保存起來媳瞪,然后再內(nèi)層函數(shù)使用:
var obj = {
? ? birth: 1990,
? ? getAge: function () {
? ? ? ? console.log(this.birth);
var self = this;
? ? ? ? var fn = function () {
? ? ? ? ? ? return new Date().getFullYear() - self.birth;
? ? ? ? };
? ? ? ? return fn();
? ? }
};
obj.getAge(); // 29
或者通過call或者apply將this傳到內(nèi)部函數(shù)中:
var obj = {
? ? birth: 1990,
? ? getAge: function () {
? ? ? ? var b = this.birth; // 1990
? ? ? ? var fn = function () {
? ? ? ? ? ? return new Date().getFullYear() - this.birth;
? ? ? ? };
? ? ? ? return fn.apply(this); // 或者:return fn.call(this);
? ? }
};
obj.getAge(); // 29
?現(xiàn)在可以通過箭頭函數(shù)的方法解決了:
var obj = {
? ? birth: 1990,
? ? getAge: function () {
? ? ? ? var b = this.birth; // 1990
? ? ? ? var fn = () => new Date().getFullYear() - this.birth; // this.birth仍是1990,因為this還是外部函數(shù)的this
? ? ? ? return fn();
? ? }
};
obj.getAge(); // 29
但是如果把外部函數(shù)也改成箭頭函數(shù)照宝,結(jié)果又是不一樣的了:
var obj = {
? ? birth: 1990,
? ? getAge:? (year) => {
? ? ? ? var b = this.birth; // 1990
? ? ? ? var fn = () => {
console.log(this); // window
? ? return new Date().getFullYear() - this.birth; // this.birth是undefined
? }
? ? ? ? return fn();
? ? }
};
obj.getAge(); // NaN
因為外部函數(shù)也是箭頭函數(shù)蛇受,所以不會有this, 就會按照作用域鏈繼續(xù)往上尋找,這段代碼的往上尋找厕鹃,找到的this是window兢仰;
所以箭頭函數(shù)this指向的關(guān)鍵是找到最近的非箭頭函數(shù)的this
(2) 沒有arguments
箭頭函數(shù)沒有自己的arguamnets對象乍丈, 但是箭頭函數(shù)可以訪問外圍函數(shù)的arguments對象;看下面兩個例子:
varFoo = () => {console.log(arguments)};
Foo(); // ReferenceError: arguments is not defined
function myFunc(age) {
var Foo = () => {console.log(arguments)};
return Foo();
}
myFunc(12);
代碼執(zhí)行結(jié)果:
第一段代碼:輸出箭頭函數(shù)的argument報錯,說明箭頭函數(shù)是沒有arguments對象的
第二段代碼:在箭頭函數(shù)中輸出的arguments對象信息name為myFunc, 說明箭頭函數(shù)中的是外圍函數(shù)的arguments, 而第一段代碼沒有外圍函數(shù)把将,所以會報錯轻专。
(3) 不能通過new關(guān)鍵字調(diào)用
js的函數(shù)有兩個內(nèi)部方法:[[call]]和[[Construct]]
當(dāng)通過new調(diào)用構(gòu)造函數(shù)時,執(zhí)行[[Construct]]方法秸弛,創(chuàng)建一個實例對象,然后再執(zhí)行函數(shù)體洪碳,將this綁定到實例上递览。當(dāng)直接調(diào)用的時候,執(zhí)行[[call]]方法瞳腌,直接執(zhí)行函數(shù)體绞铃。
箭頭函數(shù)并沒有[[Construct]]方法,不能被用作構(gòu)造函數(shù)嫂侍,因此通過new的方式調(diào)用儿捧,會報錯。
varFun = () => {};varfun =newFun();// typeError: Fun is not a constructor
(4) 沒有原型
由于不能使用new調(diào)用箭頭函數(shù)挑宠,所以也沒有構(gòu)建原型的需求菲盾,于是箭頭函數(shù)也不存在prototype這個屬性。
varFun = () => {};
console.log(Fun.prototype); // undefined
(5) 沒有super
箭頭函數(shù)沒有原型各淀,所以不能通過super來訪問原型的屬性懒鉴,所以箭頭函數(shù)是沒有super的,super的值由最近一層非箭頭函數(shù)決定碎浇。