|
|
|
|
|
箭頭函數(shù)的優(yōu)點(diǎn)很多,相比于常規(guī)函數(shù),箭頭函數(shù)的代碼更少更簡(jiǎn)潔了,并且沒(méi)有自己的this
,這意味著箭頭函數(shù)不用再需要定義this
。
不能使用箭頭函數(shù)的6種情況
但是箭頭函數(shù)不是在所有情況下都能取代常規(guī)函數(shù)。
這里有一些你不應(yīng)該看箭頭函數(shù)的情況。
var cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
當(dāng)你調(diào)用cat.jumps
時(shí),lives
的數(shù)量不會(huì)減少。這是因?yàn)?code>this沒(méi)有綁定到任何東西,并且會(huì)從其父作用域繼承this
的值。
我們?cè)倏聪旅嬉粋€(gè)示例。
const counter = {
count: 0,
next: () => ++this.count,
current: () => this.count
};
該counter
對(duì)象有兩種方法:current()
和next()
。該current()
方法返回當(dāng)前計(jì)數(shù)器值,該next()
方法返回下一個(gè)計(jì)數(shù)器值。
下面顯示了下一個(gè)計(jì)數(shù)器值,它應(yīng)該是 1:
console.log(counter.next());
但是,它返回NaN
。
原因是當(dāng)你在對(duì)象內(nèi)部使用箭頭函數(shù)時(shí),它會(huì)this
從封閉的詞法范圍繼承值,即本例中的全局范圍。
this.count
里面的方法next()
等價(jià)于window.count
(在網(wǎng)絡(luò)瀏覽器中)。
默認(rèn)情況下window.count
是undefined
,因?yàn)?code>window對(duì)象沒(méi)有count
屬性。該next()
方法將undefined
加1,結(jié)果NaN
。
要解決此問(wèn)題,可以使用常規(guī)函數(shù)作為對(duì)象字面量的方法,如下所示:
const counter = {
count: 0,
next() {
return ++this.count;
},
current() {
return this.count;
}
};
現(xiàn)在,調(diào)用該next()
方法將按預(yù)期返回一個(gè):
console.log(counter.next()); // 1
看看下面的這個(gè)事件處理程序:
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
如果我們點(diǎn)擊按鈕,我們會(huì)得到一個(gè) TypeError
。這是因?yàn)?code>this未綁定到按鈕,而是綁定到其父范圍。
以下Counter
使用prototype
模式的對(duì)象:
function Counter() {
this.count = 0;
}
Counter.prototype.next = () => {
return this.count;
};
Counter.prototype.current = () => {
return ++this.next;
}
這些next()
和current()
方法中的this
值引用全局對(duì)象。由于你希望方法中的this
值引用Counter
對(duì)象,因此你需要使用常規(guī)函數(shù):
function Counter() {
this.count = 0;
}
Counter.prototype.next = function () {
return this.count;
};
Counter.prototype.current = function () {
return ++this.next;
}
假設(shè)你有以下輸入文本字段:
<input type="text" name="username" id="username" placeholder="Enter a username">
并且你希望在用戶輸入用戶名時(shí)顯示問(wèn)候消息。下面<div>
顯示了將顯示問(wèn)候消息的元素:
<div id="greeting"></div>
一旦用戶輸入他們的用戶名,你就可以捕獲輸入的當(dāng)前值并將其更新為<div>
元素:
const greeting = document.querySelector('#greeting');
const username = document.querySelector('#username');
username.addEventListener('keyup', () => {
greeting.textContent = 'Hello ' + this.value;
});
但是,當(dāng)你執(zhí)行代碼時(shí),無(wú)論你鍵入什么內(nèi)容,你都會(huì)收到以下消息:
Hello undefined
這意味著this.value
事件處理程序中的 總是返回undefined
。
箭頭函數(shù)沒(méi)有自己的this
值。它使用this
封閉詞法范圍的值。在上面的例子中,this
在箭頭函數(shù)里引用了全局對(duì)象。
在 Web 瀏覽器中,全局對(duì)象是window
,該window
對(duì)象沒(méi)有value
屬性。因此,JavaScript 引擎將 value
屬性添加到window
對(duì)象并將其值設(shè)置為undefined
.
要解決此問(wèn)題,你需要改用常規(guī)函數(shù),將this
值綁定到<input>
觸發(fā)事件的元素。
username.addEventListener('keyup', function () {
input.textContent = 'Hello ' + this.value;
});
箭頭函數(shù)使代碼更清晰、更直觀的另一個(gè)地方是管理異步代碼。
Promise
使管理異步代碼變得容易得多。但是,雖然使用 Promise
,仍然需要定義在異步代碼或調(diào)用完成后運(yùn)行的函數(shù)。
這是箭頭函數(shù)的理想位置,特別是如果你的結(jié)果函數(shù)是有狀態(tài)的,引用對(duì)象中的某些內(nèi)容。
缺點(diǎn)是確保你再次了解this
如何工作。例子:
this.doSomethingAsync().then((result) => { this.storeResult(result); });
通過(guò)常規(guī)函數(shù),人們知道會(huì)發(fā)生什么。使用箭頭函數(shù),可能很難立即解讀你正在查看的內(nèi)容。
本文介紹了6種不應(yīng)使用箭頭函數(shù)的情況。通過(guò)本文的介紹,你應(yīng)該知道箭頭函數(shù)不是任何時(shí)候都可以取代常規(guī)函數(shù)。在編程中我們要選擇合適的方法,代碼簡(jiǎn)潔不是編程的唯一需要。