JavaScript中,函數(shù)可以用箭頭“=>”來定義,稱之為箭頭函數(shù),有時候也稱之為lambda表達式(lambda Expression)。箭頭函數(shù)是一個匿名函數(shù),其語法比函數(shù)表達式更簡潔,相比函數(shù)表達式,箭頭函數(shù)沒有自己的 this、arguments、super或new.target。箭頭函數(shù)更適用于那些需要匿名函數(shù)的地方,并且它不能用作構造函數(shù)。
//多個參數(shù)
(param1, param2, …, paramN) => { statements }
//只有一個參數(shù)
(param) => { statements }
//當只有一個參數(shù)時,圓括號可以省略
param => { statements }
//函數(shù)體只有一條 return語句
(param1, param2, …, paramN) => { return expression; }
//當函數(shù)體只有一條 return語句時,可以省略 return關鍵字和函數(shù)體的花括號
(param1, param2, …, paramN) => expression
//沒有參數(shù)的函數(shù)必須寫一對圓括號
() => { statements }
//加圓括號的函數(shù)體返回對象字面量表達式
params => ({foo: bar})
//支持剩余參數(shù)和默認參數(shù)
(param1, param2, …rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
statements
}
//支持參數(shù)列表解構
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
在普通函數(shù)中,this總是指向調用它的對象,如果是構造函數(shù),this指向創(chuàng)建的對象實例。箭頭函數(shù)本身沒有 this,但是它在聲明時可以捕獲其所在上下文的 this。例如:
var msg = "hello";
let func = () => {
console.log(this.msg);
};
func();//hello
在上面的代碼中,箭頭函數(shù)在全局作用域聲明,所以它捕獲全局作用域中的 this,this.msg即得到全局作用域中的 msg的值"hello"。
普通函數(shù)調用后都具有一個 arguments 對象存儲實際傳遞的參數(shù),但是箭頭函數(shù)沒有這個對象。在大多數(shù)情況下,可以使用rest參數(shù)來代替arguments對象。例如:
心箭頭
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>實心箭頭</title>
<style>
.con{
width: 300px;
height: 300px;
border: 1px solid #ccc;
margin: 50px auto;
background-color:#ccc;
}
.arrow-top{
border-bottom: 10px solid #fff;
border-right: 10px solid #fff;
border-left: 10px solid #fff;
border-top: 10px solid #ccc;
width: 0px;
height: 0px;
position: relative;
top:-40px;
left:100px;
}
.arrow-bottom{
border-bottom: 10px solid #fff;
border-right: 10px solid #fff;
border-left: 10px solid #fff;
border-top: 10px solid #ccc;
width: 0px;
height: 0px;
position: relative;
top:-40px;
left:100px;
}
</style>
</head>
<body>
<div class="con">
<div class="arrow-top"> </div>
</div>
</body>
</html>
非實心箭頭
S6中,除了let和const新特性,箭頭函數(shù)是使用頻率最高的新特性了。如果你曾經了解如日中天的JavaScript衍生語言CoffeeScript, 就會清楚此特性并非ES6獨創(chuàng)。箭頭函數(shù)顧名思義是使用箭頭(=>)定義的函數(shù),屬于匿名函數(shù)一類。
今天的文章內容將會從以下幾個方面,介紹箭頭函數(shù):
本篇文章閱讀時間預計8分鐘
箭頭函數(shù)有四種使用語法
1、單一參數(shù)的單行箭頭函數(shù)
如下段代碼所示,很簡單:
const fn= foo =>`${foo} world`;
這是箭頭函數(shù)最簡潔的形式,常用于用作簡單的處理函數(shù),如過濾。如下段代碼所示:
let array=['a','bc','def','ghij']; array=array.filter(item=>item.length>=2);
2、多參數(shù)的單行箭頭函數(shù) 語法也很簡單,如下段代碼所示:
const fn=(foo,bar) => foo+bar
在實際開發(fā)中,函數(shù)的參數(shù)不會只有一個,在箭頭函數(shù)中,多參數(shù)的語法跟普通函數(shù)一樣,用括號包裹參數(shù)項。我們經常處理函數(shù),如排序,示例代碼如下:
let array=['a','bc','def','ghij']; array=array.sort((a,b) => a.length < b.length);
3、多行箭頭函數(shù) 單一參數(shù),如下段代碼所示:
foo => { return `${foo} world`; }
多參數(shù),如下段代碼所示:
(foo,bar) => { return foo+bar; }
4、無參數(shù)箭頭函數(shù)
如果一個箭頭函數(shù)無參數(shù)傳入,則需要用一對空的括號來表示空的參數(shù)列表。
const greet = () => 'Hello World'
以上都是被支持的箭頭函數(shù)的表達方式,其最大的好處就是簡單明了,省略了function關鍵字,而使用 => 代替。相對于傳統(tǒng)的function函數(shù),箭頭函數(shù)在簡單的函數(shù)使用中更為簡潔直觀。
書寫箭頭的函數(shù)過程中,我們應該注意以下幾點:
1、使用單行箭頭函數(shù)時,應避免換行
錯誤的用法,如下段代碼所示:
const fn=x => x*2 //SyntaxError
正確的寫法,如下:
const fn= x => x*2 //ok
2、參數(shù)列別的右括弧、箭頭應在一行
錯誤的用法,如下段代碼所示:
const fn = (x,y) //SyntaxError => { return x*y; }
下段代碼書寫是正確的:
const fn= (x,y) => { //ok return x*y } const fn= (x, y) => { //ok return x*y }
3、單行箭頭函數(shù)返回只能包含一條語句
錯誤的書寫,如下段代碼所示:
const fn1= x => x=x*2; return x+2; //SyntaxError
正確的書寫,如下段代碼所示:
const fn2= x => { x=x*2; return x+2; } //ok
4、如果單行箭頭返回一個對象,請用圓括號包裹
錯誤的書寫,如下段代碼所示,解析引擎會將其解析成一個多行箭頭函數(shù):
const ids=[1,2,3]; const users=ids.map(id=>{id:id}); //wrong:[ undefined, undefined, undefined ]
正確的書寫,如下段代碼所示:
const ids=[1,2,3]; const users=ids.map(id=>({id:id})); //Correct:[ { id: 1 }, { id: 2 }, { id: 3 } ]
箭頭函數(shù)十分簡潔,特別適合單行回調函數(shù)的定義,比如我們有以下需求:
我們有一個這樣的名字數(shù)組names,['Will','Jack','Peter','Steve','John','Hugo','Mike'],輸出序號為偶數(shù)的名字[ 'Will', 'Peter', 'John', 'Mike' ],我們如何使用箭頭函數(shù)在一行語句完成呢,如下段代碼所示:
const names=['Will','Jack','Peter','Steve','John','Hugo','Mike']; const newSet=names .map((name,index)=>({ id:index, name:name })) .filter(man => man.id %2 ==0) .map(man => [man.name]) .reduce((a,b) => a.concat(b))
事實上,箭頭函數(shù)不僅書寫簡潔,還有一個神奇的功能,就是將函數(shù)內部的this延伸上一層作用域中(綁定最近的非箭頭函數(shù)的上下文),及上一層的上下文會穿透到內層的箭頭函數(shù)中,讓我們先看一段實際的例子,如下段所示:
var Widget={ // A init:function () { // B document.addEventListener("click", function (event){ //C this.doSomething(event.type); }, false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
這段代碼會如何輸出呢,想必大家都猜到了吧,輸出undefined,為什么呢?我們在B位置內聲明了函數(shù)(C區(qū)域),this關鍵詞的指向B區(qū)域的函數(shù),由于B區(qū)域內沒有doSomething函數(shù)聲明,因此輸出undefined,ES6之前我們如何修正此問題呢?
我們可以使用bind方法改變this指向A區(qū)域Widget對象,示例代碼如下:
var Widget={ // A init:function () { // B document.addEventListener("click", (function (event) { //C this.doSomething(event.type); }).bind(this), false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
下面這種方法是我們最常用的方法,我們在B區(qū)域聲明了that變量,并將其this賦值,確保c區(qū)域this的指向至Widget對象:
var Widget={ // A init:function () { // B var that=this; document.addEventListener("click", function (event) { //C that.doSomething(event.type); console.log(that); }, false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
有了箭頭函數(shù),我們可以使用箭頭函數(shù)的this穿透功能,將this的作用域延伸至上一層B區(qū)域函數(shù),綁定最近的非箭頭函數(shù)的上下文,如下段代碼所示:
var Widget={ //A init:function () { //B document.addEventListener("click", (event) => { //C this.doSomething(event.type); }, false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
箭頭函數(shù)是不是更簡單,代碼更清晰呢。
還有一個情況需要注意,箭頭函數(shù)對上下文的綁定是強制的,無法通過call或aplly進行改變,如下段代碼所示:
function widget() { this.id=123; this.log=()=>{ console.log(this) console.log('widget log',this.id); } } var pseudoWidget={ id:456 }; new widget().log.call(pseudoWidget);//123
上述代碼會如何輸出呢,由于箭頭函數(shù)對上下文的綁定是強制的,因此this指向不會指向pseudoWidget對象,因此輸出123。
1、箭頭函數(shù)作為匿名函數(shù),是不能作為構造函數(shù)的,不能使用new
如下段代碼所示,我們使用new方法,會提示如下信息:
const B =()=>({wechat:"前端達人"}); let b = new B(); //TypeError: B is not a constructor
2、箭頭函數(shù)不綁定arguments,可以使用剩余參數(shù)(rest)解決
function A(a){ console.log(arguments); //[object Arguments] {0: 1} } var B = (b)=>{ console.log(arguments); //ReferenceError: arguments is not defined } var C = (...c)=>{ //...c即為rest參數(shù) console.log(c); //[3] } A(1); B(2); C(3);
3、箭頭函數(shù)this指向具備穿透特性,會捕獲其所在上下文的this值
4、箭頭函數(shù)沒有原型屬性
var a = ()=>{ return '前端達人'; } function b(){ return '前端達人'; } console.log(a.prototype);//undefined console.log(b.prototype);//object{...}
5、箭頭函數(shù)不能當做Generator函數(shù),不能使用yield關鍵字
6、箭頭函數(shù)對上下文的綁定是強制的,無法通過call或aplly進行改變
小節(jié)
今天的內容就介紹到這里,我們可以看出使用箭頭函能減少代碼量,更加簡介易讀。在使用箭頭函數(shù)時,我們一定要理解箭頭函數(shù)和傳統(tǒng)函數(shù)的區(qū)別,如果函數(shù)功能簡單,只是簡單的邏輯處理,盡量使用箭頭函數(shù)。
更多精彩內容,請微信關注"前端達人”公眾號!
*請認真填寫需求信息,我們會在24小時內與您取得聯(lián)系。