|
|
|
|
|
箭頭函數表達式是使用“胖箭頭”(=>
)語法編寫的匿名函數表達式。與傳統(tǒng)函數不同,箭頭函數在它們的工作方式上有一些重要的區(qū)別,還有一些語法增強。最大的功能差異是箭頭函數沒有自己的this
綁定或原型,不能用作構造函數。箭頭函數也可以寫成比傳統(tǒng)函數更緊湊的替代方案,因為它們可以省略參數周圍的括號,并添加帶有隱式返回的簡潔函數體的概念。在本文中,將演示傳統(tǒng)函數和箭頭函數如何處理this
,分析它們的不同之處。
箭頭函數沒有this值
在 JavaScript 中,關鍵字this
通常被認為是一個棘手的話題。文章詳解JS里this的上下文對象及用法解釋了this
如何工作,以及this
如何根據程序是否在全局上下文中使用它、作為對象中的方法、作為函數或類的構造函數來隱式指示,或作為DOM事件處理程序。
箭頭函數有this
語法,這意味著this
的值由周圍的范圍(詞法環(huán)境)決定。
下面一個示例將演示傳統(tǒng)函數和箭頭函數如何處理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
函數在每次迭代時在循環(huán)中打印字符串和當前數字。但是,在運行函數的結果中,phrase
實際上是undefined
:
printNumbers.loop()
這將輸出以下內容:
undefined 1
undefined 2
undefined 3
undefined 4
如上所示,this.phrase
是未定義的,表面匿名函數中的this
傳入forEach
方法沒有引用printNumbers
對象。這是因為傳統(tǒng)的函數this
不會從環(huán)境的范圍來確定它的值,也就是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
等內置數組方法中使用箭頭函數可以更直觀、更易于閱讀,從而使該策略更有可能滿足預期。
傳統(tǒng)函數和箭頭函數處理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
值,而不用創(chuàng)建自己的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
總結
箭頭函數在許多方面與傳統(tǒng)函數不同,包括確定其作用域的方式和表達語法的方式。本文詳細介紹了JS箭頭函數=>與傳統(tǒng)匿名函數處理this
的不同方法,希望看了本文的你,對箭頭函數和傳統(tǒng)函數會有進一步的認識。
參考文章