您好,登錄后才能下訂單哦!
今天小編給大家分享一下箭頭函數是不是屬于es6的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
箭頭函數屬于es6。箭頭函數是ES6中引入的新特性,使用箭頭“=>”定義函數,例“var f = v => v;”,等價于“var f = function (v) {return v;};”;如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分,例“var f = () => 5;”。
箭頭函數是ES6中引入的新特性,使用“箭頭”(=>)定義函數。由于其簡潔的語法和對this關鍵字的處理,箭頭函數迅速成為開發者們最喜愛的功能。
var f = v => v;
// 等同于
var f = function (v) {
return v;
};
如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分。
var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
如果箭頭函數的代碼塊部分多于一條語句,就要使用大括號將它們括起來,并且使用return語句返回。
var sum = (num1, num2) => { return num1 + num2; }
由于大括號被解釋為代碼塊,所以如果箭頭函數直接返回一個對象,必須在對象外面加上括號,否則會報錯。
// 報錯
let getTempItem = id => { id: id, name: "Temp" };
// 不報錯
let getTempItem = id => ({ id: id, name: "Temp" });
下面是一種特殊情況,雖然可以運行,但會得到錯誤的結果。
let foo = () => { a: 1 };
foo() // undefined
上面代碼中,原始意圖是返回一個對象{ a: 1 },但是由于引擎認為大括號是代碼塊,所以執行了一行語句a: 1。這時,a可以被解釋為語句的標簽,因此實際執行的語句是1;,然后函數就結束了,沒有返回值。
如果箭頭函數只有一行語句,且不需要返回值,可以采用下面的寫法,就不用寫大括號了。
let fn = () => void doesNotReturn();
說明:
箭頭函數是函數式編程的一種體現,函數式編程將更多的關注點放在輸入和輸出的關系,省去了過程的一些因素,因此箭頭函數中沒有自己的this,arguments,new target(ES6)和 super(ES6)。箭頭函數相當于匿名函數,因此不能使用new來作為構造函數使用。
箭頭函數中的this始終指向其父級作用域中的this。換句話說,箭頭函數會捕獲其所在的上下文的this值,作為自己的this值。任何方法都改變不了其指向,如call(), bind(), apply()。在箭頭函數中調用 this 時,僅僅是簡單的沿著作用域鏈向上尋找,找到最近的一個 this 拿來使用,它與調用時的上下文無關。我們用代碼來解釋一下。
在函數體內只有一個表達式時,你可以讓ES6的箭頭語法更加簡潔。你可以把所有內容放在一行,去掉大括號,并移除return
關鍵字。
你已經在上面的示例中看到了這些漂亮的一行代碼是如何工作的。下面的orderByLikes()
函數返回奈飛劇集對象的數組,按照最高點贊數排序:
// using the JS sort() function to sort the titles in descending order
// according to the number of likes (more likes at the top, fewer at the bottom
const orderByLikes = netflixSeries.sort((a, b) => b.likes - a.likes)
// call the function
// output:the titles and the n. of likes in descending order
console.log(orderByLikes)
這種寫法很酷,但是要注意代碼的可讀性。特別是在使用單行和無括號的ES6箭頭語法對一堆箭頭函數進行排序時。就像這個例子:
const greeter = greeting => name => `${greeting}, ${name}!`
那里發生了什么?嘗試使用常規的函數語法:
function greeter(greeting) {
return function(name) {
return `${greeting}, ${name}!`
}
}
現在,你可以快速看到外部函數greeter
如何具有參數greeting
,并返回一個匿名函數。這個內部函數又有一個叫做name
的參數,并使用greeting
和name
的值返回一個字符串。下面是調用函數的方式:
const myGreet = greeter('Good morning')
console.log( myGreet('Mary') )
// output:
"Good morning, Mary!"
當你的JavaScript箭頭函數包含不止一個語句,你需要在大括號內包裹所有語句,并使用return
關鍵字。
在下面的代碼中,該函數建立了一個包含幾個Netflix劇集的標題和摘要的對象:
const seriesList = netflixSeries.map( series => {
const container = {}
container.title = series.name
container.summary = series.summary
// explicit return
return container
} )
.map()
函數中的箭頭函數在一系列的語句中展開,在語句的最后返回一個對象。這使得在函數主體周圍使用大括號是不可避免的。
另外,由于正在使用花括號,隱式返回便不是一個選項。你必須顯式使用return
關鍵字。
如果你的函數使用隱式返回來返回一個對象字面量,你需要使用圓括號來包裹該對象字面量。不這樣做將導致錯誤,因為JavaScript引擎將對象字面量的大括號錯誤地解析為函數的大括號。正如你剛才注意到的,當你在一個箭頭函數中使用大括號時,你不能省略return
關鍵字。
前面代碼的較短版本演示了這種語法:
// Uncaught SyntaxError: unexpected token: ':'
const seriesList = netflixSeries.map(series => { title: series.name });
// Works fine
const seriesList = netflixSeries.map(series => ({ title: series.name }));
在function
關鍵字和參數列表之間沒有名稱標識的函數被稱為匿名函數。下面是常規匿名函數表達式的樣子:
const anonymous = function() {
return 'You can\'t identify me!'
}
箭頭函數都是匿名函數:
const anonymousArrowFunc = () => 'You can\'t identify me!'
從ES6開始,變量和方法可以通過匿名函數的語法位置,使用name
屬性來推斷其名稱。這使得在檢查函數值或報告錯誤時有可能識別該函數。
使用anonymousArrowFunc
檢查一下:
console.log(anonymousArrowFunc.name)
// output: "anonymousArrowFunc"
需要注意的是,只有當匿名函數被分配給一個變量時,這個可以推斷的name
屬性才會存在,正如上面的例子。如果你使用匿名函數作為回調函數,你就會失去這個有用的功能。在下面的演示中,.setInterval()
方法中的匿名函數無法利用name
屬性:
let counter = 5
let countDown = setInterval(() => {
console.log(counter)
counter--
if (counter === 0) {
console.log("I have no name!!")
clearInterval(countDown)
}
}, 1000)
這還不是全部。這個推斷的name
屬性仍然不能作為一個適當的標識符,你可以用它來指代函數本身--比如遞歸、解除綁定事件等。
關于箭頭函數,最重要的一點是它們處理this
關鍵字的方式。特別是,箭頭函數內的this
關鍵字不會重新綁定。
為了說明這意味著什么,請查看下面的演示。
這里有一個按鈕。點擊按鈕會觸發一個從5到1的反向計數器,它顯示在按鈕本身。
<button class="start-btn">Start Counter</button>
...
const startBtn = document.querySelector(".start-btn");
startBtn.addEventListener('click', function() {
this.classList.add('counting')
let counter = 5;
const timer = setInterval(() => {
this.textContent = counter
counter --
if(counter < 0) {
this.textContent = 'THE END!'
this.classList.remove('counting')
clearInterval(timer)
}
}, 1000)
})
注意到.addEventListener()
方法里面的事件處理器是一個常規的匿名函數表達式,而不是一個箭頭函數。為什么呢?如果在函數內部打印this
的值,你會看到它引用了監聽器所連接的按鈕元素,這正是我們所期望的,也是程序按計劃工作所需要的:
startBtn.addEventListener('click', function() {
console.log(this)
...
})
下面是它在Firefox開發人員工具控制臺中的樣子:
然后,嘗試使用箭頭函數來替代常規函數,就像這樣:
startBtn.addEventListener('click', () => {
console.log(this)
...
})
現在,this
不再引用按鈕元素。相反,它引用Window
對象:
這意味著,如果你想要在按鈕被點擊之后,使用this
來為按鈕添加class
,你的代碼就無法正常工作:
// change button's border's appearance
this.classList.add('counting')
下面是控制臺中的錯誤信息:
當你在JavaScript中使用箭頭函數,this
關鍵字的值不會被重新綁定。它繼承自父作用域(也稱為詞法作用域)。在這種特殊情況下,箭頭函數被作為參數傳遞給startBtn.addEventListener()
方法,該方法位于全局作用域中。因此,函數處理器中的this
也被綁定到全局作用域中--也就是Window
對象。
因此,如果你想讓this
引用程序中的開始按鈕,正確的做法是使用一個常規函數,而不是一個箭頭函數。
在上面的演示中,接下來要注意的是.setInterval()
方法中的代碼。在這里,你也會發現一個匿名函數,但這次是一個箭頭函數。為什么?
請注意,如果你使用常規函數,this
值會是多少:
const timer = setInterval(function() {
console.log(this)
...
}, 1000)
是button
元素嗎?并不是。這個值將會是Window
對象!
事實上,上下文已經發生了變化,因為現在this
在一個非綁定的或全局的函數中,它被作為參數傳遞給.setInterval()
。因此,this
關鍵字的值也發生了變化,因為它現在被綁定到全局作用域。
在這種情況下,一個常見的hack手段是包括另一個變量來存儲this
關鍵字的值,這樣它就會一直指向預期的元素--在這種情況下,就是button
元素:
const that = this
const timer = setInterval(function() {
console.log(that)
...
}, 1000)
你也可以使用.bind()
來解決這個問題:
const timer = setInterval(function() {
console.log(this)
...
}.bind(this), 1000)
有了箭頭函數,問題就徹底消失了。下面是使用箭頭函數時this
的值:
const timer = setInterval( () => {
console.log(this)
...
}, 1000)
這次,控制臺打印了button
,這就是我們想要的。事實上,程序要改變按鈕的文本,所以它需要this
來指代button
元素:
const timer = setInterval( () => {
console.log(this)
// the button's text displays the timer value
this.textContent = counter
}, 1000)
箭頭函數沒有自己的this
上下文。它們從父級繼承this
的值,正是因為這個特點,在上面這種情況下就是很好的選擇。
箭頭函數并不只是在JavaScript中編寫函數的一種花里胡哨的新方法。它們有自己的局限性,這意味著在有些情況下你不想使用箭頭函數。讓我們看看更多的例子。
箭頭函數作為對象上的方法不能很好地工作。
考慮這個netflixSeries
對象,上面有一些屬性和一系列方法。調用console.log(netflixSeries.getLikes())
應該會打印一條信息,說明當前喜歡的人數。console.log(netflixSeries.addLike())
應該會增加一個喜歡的人數,然后在控制臺上打印新值:
const netflixSeries = {
title: 'After Life',
firstRealease: 2019,
likes: 5,
getLikes: () => `${this.title} has ${this.likes} likes`,
addLike: () => {
this.likes++
return `Thank you for liking ${this.title}, which now has ${this.likes} likes`
}
}
相反,調用.getLikes()
方法返回'undefined has NaN likes'
,調用.addLike()
方法返回'Thank you for liking undefined, which now has NaN likes'
。因此,this.title
和this.likes
未能分別引用對象的屬性title
和likes
。
這次,問題出在箭頭函數的詞法作用域上。對象方法中的this
引用的是父對象的范圍,在本例中是Window
對象,而不是父對象本身--也就是說,不是netflixSeries
對象。
當然,解決辦法是使用常規函數:
const netflixSeries = {
title: 'After Life',
firstRealease: 2019,
likes: 5,
getLikes() {
return `${this.title} has ${this.likes} likes`
},
addLike() {
this.likes++
return `Thank you for liking ${this.title}, which now has ${this.likes} likes`
}
}
// call the methods
console.log(netflixSeries.getLikes())
console.log(netflixSeries.addLike())
// output:
After Life has 5 likes
Thank you for liking After Life, which now has 6 likes
另一個需要注意的問題是,第三方庫通常會綁定方法調用,因此this
值會指向一些有用的東西。
比如說,在Jquery事件處理器內部,this
將使你能夠訪問處理器所綁定的DOM元素:
$('body').on('click', function() {
console.log(this)
})
// <body>
但是如果我們使用箭頭函數,正如我們所看到的,它沒有自己的this
上下文,我們會得到意想不到的結果:
$('body').on('click', () =>{
console.log(this)
})
// Window
下面是使用Vue的其他例子:
new Vue({
el: app,
data: {
message: 'Hello, World!'
},
created: function() {
console.log(this.message);
}
})
// Hello, World!
在created
鉤子內部,this
被綁定到Vue實例上,因此會顯示'Hello, World!'
信息。
然而如果我們使用箭頭函數,this
將會指向父作用域,上面沒有message
屬性:
new Vue({
el: app,
data: {
message: 'Hello, World!'
},
created: () => {
console.log(this.message);
}
})
// undefined
arguments
對象有時,你可能需要創建一個具有無限參數個數的函數。比如,假設你想創建一個函數,列出你最喜歡的奈飛劇集,并按照偏好排序。然而,你還不知道你要包括多少個劇集。JavaScript提供了arguments
對象。這是一個類數組對象(不是完整的數組),在調用時存儲傳遞給函數的值。
嘗試使用箭頭函數實現此功能:
const listYourFavNetflixSeries = () => {
// we need to turn the arguments into a real array
// so we can use .map()
const favSeries = Array.from(arguments)
return favSeries.map( (series, i) => {
return `${series} is my #${i +1} favorite Netflix series`
} )
console.log(arguments)
}
console.log(listYourFavNetflixSeries('Bridgerton', 'Ozark', 'After Life'))
當你調用該函數時,你會得到以下錯誤:Uncaught ReferenceError: arguments is not defined
。這意味著arguments
對象在箭頭函數中是不可用的。事實上,將箭頭函數替換成常規函數就可以了:
const listYourFavNetflixSeries = function() {
const favSeries = Array.from(arguments)
return favSeries.map( (series, i) => {
return `${series} is my #${i +1} favorite Netflix series`
} )
console.log(arguments)
}
console.log(listYourFavNetflixSeries('Bridgerton', 'Ozark', 'After Life'))
// output:
["Bridgerton is my #1 favorite Netflix series", "Ozark is my #2 favorite Netflix series", "After Life is my #3 favorite Netflix series"]
因此,如果你需要arguments
對象,你不能使用箭頭函數。
但如果你真的想用一個箭頭函數來復制同樣的功能呢?你可以使用ES6剩余參數(...
)。下面是你該如何重寫你的函數:
const listYourFavNetflixSeries = (...seriesList) => {
return seriesList.map( (series, i) => {
return `${series} is my #${i +1} favorite Netflix series`
} )
}
以上就是“箭頭函數是不是屬于es6”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。