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