|
|
|
|
|
|
箭頭函數表達式是使用“胖箭頭”(=>)語法編寫的匿名函數表達式。與傳統函數不同,箭頭函數在它們的工作方式上有一些重要的區別,還有一些語法增強。最大的功能差異是箭頭函數沒有自己的this綁定或原型,不能用作構造函數。箭頭函數也可以寫成比傳統函數更緊湊的替代方案,因為它們可以省略參數周圍的括號,并添加帶有隱式返回的簡潔函數體的概念。在本文中,將演示傳統函數和箭頭函數如何處理this,分析它們的不同之處。

箭頭函數沒有this值
在 JavaScript 中,關鍵字this通常被認為是一個棘手的話題。文章詳解JS里this的上下文對象及用法解釋了this如何工作,以及this如何根據程序是否在全局上下文中使用它、作為對象中的方法、作為函數或類的構造函數來隱式指示,或作為DOM事件處理程序。
箭頭函數有this語法,這意味著this的值由周圍的范圍(詞法環境)決定。
下面一個示例將演示傳統函數和箭頭函數如何處理this.。
在以下printNumbers對象中,有兩個屬性:phrase和numbers。對象上還有一個方法loop,它應該打印phrase字符串和當前值numbers:
const printNumbers = {
phrase: '當前值是:',
numbers: [1, 2, 3, 4],
loop() {
this.numbers.forEach(function (number) {
console.log(this.phrase, number)
})
},
}人們可能期望該loop函數在每次迭代時在循環中打印字符串和當前數字。但是,在運行函數的結果中,phrase實際上是undefined:
printNumbers.loop()
這將輸出以下內容:
undefined 1
undefined 2
undefined 3
undefined 4
如上所示,this.phrase是未定義的,表面匿名函數中的this傳入forEach方法沒有引用printNumbers對象。這是因為傳統的函數this不會從環境的范圍來確定它的值,也就是printNumbers對象。
在舊版本的 JavaScript 中,不得不使用bind顯式設置this。
使用bind改正上面的函數:
const printNumbers = {
phrase: '當前值是:',
numbers: [1, 2, 3, 4],
loop() {
// 從printNumbers綁定`this`到內部forEach函數
this.numbers.forEach(
function (number) {
console.log(this.phrase, number)
}.bind(this),
)
},
}
printNumbers.loop()這將輸出預期的結果:
當前值是: 1
當前值是: 2
當前值是: 3
當前值是: 4
箭頭函數可以提供更直接的處理方式。由于它們的this值是根據詞法范圍確定的,因此內部函數forEach可以訪問外部printNumbers對象的屬性,如下所示:
const printNumbers = {
phrase: '當前值是:',
numbers: [1, 2, 3, 4],
loop() {
this.numbers.forEach((number) => {
console.log(this.phrase, number)
})
},
}
printNumbers.loop()這將輸出預期的結果:
當前值是: 1
當前值是: 2
當前值是: 3
當前值是: 4
這些示例表明,在forEach、map、filter和reduce等內置數組方法中使用箭頭函數可以更直觀、更易于閱讀,從而使該策略更有可能滿足預期。
傳統函數和箭頭函數處理this值的不同方法
在 JavaScript 中,一個新函數定義了它自己的this值。但是,該this值并不能直接在匿名函數內部使用。請參見以下示例:
function Car() {
this.speed = 0;
this.speedUp = function (speed) {
this.speed = speed;
setTimeout(function () {
console.log(this.speed);
}, 1000);
};
}
let car = new Car();
car.speedUp(50);輸出:
undefined
在setTimeout()函數的匿名函數內部,this.speed是undefined,原因是匿名函數的this隱藏了speedUp()方法。
要解決此問題,請將this值分配給不會在匿名函數內隱藏的變量,如下所示:
function Car() {
this.speed = 0;
this.speedUp = function (speed) {
this.speed = speed;
let self = this;
setTimeout(function () {
console.log(self.speed);
}, 1000);
};
}
let car = new Car();
car.speedUp(50);輸出:
50
箭頭函數能獲取封閉上下文的this值
與匿名函數不同,箭頭函數會捕獲封閉上下文的this值,而不用創建自己的this上下文。以下代碼應按預期工作:
function Car() {
this.speed = 0;
this.speedUp = function (speed) {
this.speed = speed;
setTimeout(
() => console.log(this.speed),
1000);
};
}
let car = new Car();
car.speedUp(50);
輸出:
50
總結
箭頭函數在許多方面與傳統函數不同,包括確定其作用域的方式和表達語法的方式。本文詳細介紹了JS箭頭函數=>與傳統匿名函數處理this的不同方法,希望看了本文的你,對箭頭函數和傳統函數會有進一步的認識。
參考文章
