ES6標準 Arrow Function(箭頭函數=>)
ES6標準新增了一種新的函數:Arrow Function(箭頭函數),為什么叫Arrow Function?因為它的定義用的就是一個箭頭ES6—箭頭函數0.為什么會出現箭頭函數?1.傳統的javascript函數...
ES6標準新增了一種新的函數:Arrow Function(箭頭函數),為什么叫Arrow Function?因為它的定義用的就是一個箭頭
ES6—箭頭函數
0.為什么會出現箭頭函數?
1.傳統的javascript函數語法并沒有提供任何的靈活性,每一次你需要定義一個函數時,你都必須輸入function () {},這至少會出現兩個問題,ES6箭頭函數都圓滿解決了它,
第一個問題:代碼輸入快了容易輸錯成 funciton或者functoin或者其它,但是=>這個玩意你要是再寫錯就只能說有點過分了。
第二個問題:節省大量代碼,我們先不用管下面的ES6代碼為什么這樣的語法能實現同樣的功能,我們就直觀的感受一下代碼量。
ES5寫法:
function addFive(num){
return num+5;
}
alert(addFive(10));
ES6寫法:
var addFive = num=>num+5;
alert(addFive(5));
沒有function、沒有return,沒有(),沒有{},這些全變成了浮云,世界好清靜。
從上面我們就可以看到,使用箭頭函數不僅僅能夠避免錯誤,同時還能讓我們少一丟丟代碼,當然實際工作中遠比這個代碼量節省更多。
一方面是因為積累效應,每一部分少一丟丟合起來就多了,一方面是它還有更能節省代碼和大幅提高工作效率的場景。
接下來我們就說說今天的主角--箭頭函數。
ES6標準新增了一種新的函數:Arrow Function(箭頭函數),也稱“胖箭頭函數”, 允許
使用“箭頭”(=>)定義函數,是一種簡寫的函數表達式。
1、箭頭函數語法
在ES5中我們實現一個求和的函數:
var sum = function(x, y) {
return x + y
}
要使用箭頭函數,可以分兩步實現同樣的函數功能:
首先使用=>來替代關鍵詞function
var sum = (x, y) => {
return x + y
}
這個特性非常好!!!
前面我們已經說過用=>來替代關鍵詞function就意味著不會寫錯function了,這真是一個絕妙的設計思想!
其次,函數體只有一條返回語句時, 我們可以省略括號{}和return關鍵詞:
var sum = (x, y) => x + y
再夸張一點點,如果只有一個參數時,()可省略。
這是箭頭函數最簡潔的形式,常用于作用簡單的處理函數,比如過濾:
// ES5
var array = ['1', '2345', '567', '89'];
array = array.filter(function (item) {
return item.length > 2;
});
// ["2345", "567"]
// ES6
let array = ['1', '2345', '567', '89'];
array = array.filter(item => item.length > 2);
// ["2345", "567"]
箭頭函數的主要使用模式如下:
// 一個參數對應一個表達式
param => expression;// 例如 x => x+2;
// 多個參數對應一個表達式
(param [, param]) => expression; //例如 (x,y) => (x + y);
// 一個參數對應多個表示式
param => {statements;} //例如 x = > { x++; return x;};
// 多個參數對應多個表達式
([param] [, param]) => {statements} // 例如 (x,y) => { x++;y++;return x*y;};
//表達式里沒有參數
() => expression; //例如var flag = (() => 2)(); flag等于2
() => {statements;} //例如 var flag = (() => {return 1;})(); flag就等于1
//傳入一個表達式,返回一個對象
([param]) => ({ key: value });
//例如 var fuc = (x) => ({key:x})
var object = fuc(1);
alert(object);//{key:1}
大家不要覺得好多啊,好麻煩,其實這些根本不復雜。投入一次,受益終生。(怎么感覺我像賣保險的……),寫一兩次你就習慣新的寫法了。
2、箭頭函數中的 this
箭頭函數內的this值繼承自外圍作用域。運行時它會首先到它的父作用域找,如果父作用域還是箭頭函數,那么接著向上找,直到找到我們要的this指向。
我們先看一道經典的關于this的面試題:
var name = 'leo';
var teacher = {
name: "大彬哥",
showName: function () {
function showTest() {
alert(this.name);
}
showTest();
}
};
teacher.showName();//結果是 leo,而我們期待的是大彬哥,這里this指向了window,我們期待指向teacher
大家知道,ES5中的this說好聽了叫"靈活",說不好聽就是瞎搞,特別容易出問題.而且面試還非常愛考,工作更不用說了,經常給我們開發搗亂,出現不好調試的bug,用E箭頭函數解決這個問題就很得心應手了。
var name = 'leo';
var teacher = {
name: "大彬哥",
showName: function () {
let showTest = ()=>alert(this.name);
showTest();
}
};
teacher.showName();
箭頭函數中的this其實是父級作用域中的this。箭頭函數引用了父級的變量詞法作用域就是一個變量的作用在定義的時候就已經被定義好,當在本作用域中找不到變量,就會一直向父作用域中查找,直到找到為止。
由于this在箭頭函數中已經按照詞法作用域綁定了,所以,用call或者apply調用箭頭函數時,無法對this進行綁定,即傳入的第一個參數被忽略:
var obj = {
birth: 1996,
getAge: function (year) {
var b = this.birth; // 1996
var fn = (y) => y - this.birth; // this.birth仍是1996
return fn.call({birth:1990}, year);
}
};
obj.getAge(2018); // 22 ( 2018 - 1996)
由于this已經在詞法層面完成了綁定,通過call或apply方法調用一個函數時,只是傳入了參數而已,對this并沒有什么影響 。因此,這個設計節省了開發者思考上下文綁定的時間。3、箭頭函數的特性
3.1 箭頭函數沒有 arguments
箭頭函數不僅沒有this,常用的arguments也沒有。如果你能獲取到arguments,那它
一定是來自父作用域的。
function foo() {
return () => console.log(arguments)
}
foo(1, 2)(3, 4) // 1,2
上例中如果箭頭函數有arguments,就應該輸出的是3,4而不是1,2。
箭頭函數不綁定arguments,取而代之用rest參數…解決
var foo = (...args) => {
return args
}
console.log(foo(1,3,56,36,634,6)) // [1, 3, 56, 36, 634, 6]
箭頭函數要實現類似純函數的效果,必須剔除外部狀態。我們可以看出,箭頭函數除了傳入的參數之外,真的在普通函數里常見的this、arguments、caller是統統沒有的!
如果你在箭頭函數引用了this、arguments或者參數之外的變量,那它們一定不是箭頭函數本身包含的,而是從父級作用域繼承的。
3.2 箭頭函數中不能使用 new
this.name = name;
};
let one = new Person("galler");
運行該程序,則出現TypeError: Person is not a constructor
3.3 箭頭函數可以與變量解構結合使用。
const full = ({ first, last }) => first + ' ' + last;
// 等同于
function full(person) {
return person.first + ' ' + person.last;
}
full({first: 1, last: 5}) // '1 5'
3.4 箭頭函數沒有原型屬性
var foo = () => {};
console.log(foo.prototype) //undefined
由此可以看出箭頭函數沒有原型。
另一個錯誤是在原型上使用箭頭函數,如:
function A() {
?this.foo = 1
}
?
A.prototype.bar = () => console.log(this.foo)
?
let a = new A()
a.bar() //undefined
同樣,箭頭函數中的this不是指向A,而是根據變量查找規則回溯到了全局作用域。同樣,使用普通函數就不存在問題。箭頭函數中不可加new,也就是說箭頭函數不能當構造函數進行使用。
3.5 箭頭函數不能換行
var func = ()
??????=> 1; // SyntaxError: expected expression, got '=>'
如果開發中確實一行搞不定,邏輯很多,就加{},你就想怎么換行怎么換行了。
var func = ()=>{
??return '來啊!互相傷害啊!'; // 1.加{} 2.加return
}
4、箭頭函數使用場景
JavaScript中this的故事已經是非常古老了,每一個函數都有自己的上下文。
以下例子的目的是使用jQuery來展示一個每秒都會更新的時鐘:
$('.time').each(function () {
?setInterval(function () {
??$(this).text(Date.now());
?}, 1000);
});
當嘗試在setInterval的回調中使用this來引用DOM元素時,很不幸,我們得到的只是一個屬于回調函數自身
上下文的this。一個通常的解決辦法是定義一個that或者self變量:
$('.time').each(function () {
?var self = this;
?setInterval(function () {
??$(self).text(Date.now());
?}, 1000);
});
但當使用箭頭函數時,這個問題就不復存在了。因為它不產生屬于它自己上下文的this:
$('.time').each(function () {
?setInterval(() => $(this).text(Date.now()), 1000);
});
箭頭函數的另一個用處是簡化回調函數。
// 正常函數寫法
[1,2,3].map(function (x) {
?return x * x;
});
?
// 箭頭函數寫法
[1,2,3].map(x => x * x);
當然也可以在事件監聽函數里使用:
document.body.addEventListener('click', event=>console.log(event, this));
// EventObject, BodyElement
5、總結
5.1 箭頭函數優點
箭頭函數是使用=>語法的函數簡寫形式。這在語法上與 C#、Java 8 、Python( lambda 函數)和 CoffeeScript 的
相關特性非常相似。
非常簡潔的語法,使用箭頭函數比普通函數少些動詞,如:function或return。
() => { ... } // 零個參數用 () 表示。
x => { ... } // 一個參數可以省略 ()。
(x, y) => { ... } // 多參數不能省略 ()。
如果只有一個return,{}可以省略。
更直觀的作用域和 this的綁定,它能讓我們能很好的處理this的指向問題。箭頭函數加上let關鍵字的使用,將會讓我們javascript代碼上一個層次。
5.2 箭頭函數使用場景
箭頭函數適合于無復雜邏輯或者無副作用的純函數場景下,例如用在map、reduce、filter的回調函數定義
中,另外目前vue、react、node等庫,都大量使用箭頭函數,直接定義function的情況已經很少了。
各位同學在寫新項目的時候,要不斷的琢磨箭頭函數使用場景、特點,享受使用箭頭函數帶來的便利,這樣才能更快地成長。
下面是廖雪峰網站的補充
ES6標準新增了一種新的函數:Arrow Function(箭頭函數)。
為什么叫Arrow Function?因為它的定義用的就是一個箭頭:
x => x * x
上面的箭頭函數相當于:
function (x) {
return x * x;
}
箭頭函數相當于匿名函數,并且簡化了函數定義。箭頭函數有兩種格式,一種像上面的,只包含一個表達式,連{ ... }和return都省略掉了。還有一種可以包含多條語句,這時候就不能省略{ ... }和return:
>
x => {
?if (x > 0) {
??return x * x;
?}
?else {
??return - x * x;
?}
}
如果參數不是一個,就需要用括號()括起來:
// 兩個參數:
(x, y) => x * x + y * y
?
// 無參數:
() => 3.14
?
// 可變參數:
(x, y, ...rest) => {
?var i, sum = x + y;
?for (i=0; i<rest.length; i++) {
??sum += rest[i];
?}
?return sum;
}
如果要返回一個對象,就要注意,如果是單表達式,這么寫的話會報錯:
// SyntaxError:
x => { foo: x }
因為和函數體的{ ... }有語法沖突,所以要改為:
// ok:
x => ({ foo: x })
this
箭頭函數看上去是匿名函數的一種簡寫,但實際上,箭頭函數和匿名函數有個明顯的區別:箭頭函數內部的this是詞法作用域,由上下文確定。
回顧前面的例子,由于JavaScript函數對this綁定的錯誤處理,下面的例子無法得到預期結果:
var obj = {
?birth: 1990,
?getAge: function () {
??var b = this.birth; // 1990
??var fn = function () {
???return new Date().getFullYear() - this.birth; // this指向window或undefined
??};
??return fn();
?}
};
現在,箭頭函數完全修復了this的指向,this總是指向詞法作用域,也就是外層調用者obj:
var obj = {
?birth: 1990,
?getAge: function () {
??var b = this.birth; // 1990
??var fn = () => new Date().getFullYear() - this.birth; // this指向obj對象
??return fn();
?}
};
obj.getAge(); // 25
如果使用箭頭函數,以前的那種hack寫法:
var that = this;
就不再需要了。
由于this在箭頭函數中已經按照詞法作用域綁定了,所以,用call()或者apply()調用箭頭函數時,無法對this進行綁定,即傳入的第一個參數被忽略:
var obj = {
?birth: 1990,
?getAge: function (year) {
??var b = this.birth; // 1990
??var fn = (y) => y - this.birth; // this.birth仍是1990
??return fn.call({birth:2000}, year);
?}
};
obj.getAge(2015); // 25
練習
請使用箭頭函數簡化排序時傳入的函數:
<script>
'use strict'
var arr = [10, 20, 1, 2];
arr.sort((x, y) => {
?if (x < y) return -1
?else if (x > y) return 1
?else return 0
});
console.log(arr); // [1, 2, 10, 20]
</script>
以上就是ES6標準 Arrow Function(箭頭函數=>)的詳細內容
如何寫JavaScript才能逼格更高呢?JavaScript的裝逼指南(js另類寫法)
如何寫JavaScript才能逼格更高呢?是否很期待別人在看完你的代碼之后感嘆一句原來還可以這樣寫呢?下面列出一些在JavaScript時的裝逼技巧,也可說是非常實用的寫法...
蔚來將推送新車機系統:提升老款ES6/ES8懸架的舒適性
4月21日消息,從蔚來官方獲悉,蔚來將在4月底向老款ES8以及ES6推送最新版本車機系統,系統代號NIO OS 2.6.0。據悉,剛剛開始交付的2020款ES8搭載的就是這套最新的車機系統。...
JavaScript圖片文字識別(OCR)插件Ocrad.js教程
文章主要為大家詳細介紹了圖片文字識別(OCR)插件Ocrad.js教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下Ocrad.js 相當于是 Ocrad 項目的純 JavaScript 版本,使用 Emscri...
Javascript類庫:vue.js中的vue-resource示例詳解
Vue與后臺Api進行交互通常是利用vue-resource來實現的,本質上vue-resource是通過http來完成AJAX請求相應的。這篇文章主要介紹了Vue中的vue-resource示例詳解,需要的朋友可以...
javascript類庫:element ui table 增加篩選的方法示例
文章主要介紹了element ui table 增加篩選的方法示例,詳細的介紹了如何添加規則內容,具有一定的參考價值,感興趣的小伙伴們可以參考一下網上大部分都可以增加篩選功能,但沒有找...
PHP遭棄用!Wordpress.com開源并轉用Javascript
據外媒消息稱,Wordpress母公司Automattic將完全重寫Wordpress.com網站代碼,并將此項計劃命名為“Calypso”,代碼開源并被托管于Github平臺。此外,最新的wordpress.com放...