摘要:因為它不產(chǎn)生屬于它自己上下文的箭頭函數(shù)的另一個用處是簡化回調(diào)函數(shù)。箭頭函數(shù)使用場景箭頭函數(shù)適合于無復(fù)雜邏輯或者無副作用的純函數(shù)場景下,例如用在的回調(diào)函數(shù)定義中,另外目前等庫,都大量使用箭頭函數(shù),直接定義的情況已經(jīng)很少了。
0.為什么會出現(xiàn)箭頭函數(shù)?
1.傳統(tǒng)的javascript函數(shù)語法并沒有提供任何的靈活性,每一次你需要定義一個函數(shù)時,你都必須輸入function () {},這至少會出現(xiàn)兩個問題,ES6箭頭函數(shù)都圓滿解決了它,
第一個問題:代碼輸入快了容易輸錯成 funciton或者functoin或者其它,但是=>這個玩意你要是再寫錯就只能說有點過分了。
第二個問題:節(jié)省大量代碼,我們先不用管下面的ES6代碼為什么這樣的語法能實現(xiàn)同樣的功能,我們就直觀的感受一下代碼量。
ES5寫法:
function addFive(num){ return num+5; } alert(addFive(10));
ES6寫法:
var addFive = num=>num+5; alert(addFive(5));
沒有function、沒有return,沒有(),沒有{},這些全變成了浮云,世界好清靜。
從上面我們就可以看到,使用箭頭函數(shù)不僅僅能夠避免錯誤,同時還能讓我們少一丟丟代碼,當然實際工作中遠比這個代碼量節(jié)省更多。
一方面是因為積累效應(yīng),每一部分少一丟丟合起來就多了,一方面是它還有更能節(jié)省代碼和大幅提高工作效率的場景。
接下來我們就說說今天的主角--箭頭函數(shù)。
ES6標準新增了一種新的函數(shù):Arrow Function(箭頭函數(shù)),也稱“胖箭頭函數(shù)”, 允許
使用“箭頭”(=>)定義函數(shù),是一種簡寫的函數(shù)表達式。
1、箭頭函數(shù)語法
在ES5中我們實現(xiàn)一個求和的函數(shù):
var sum = function(x, y) { return x + y }
要使用箭頭函數(shù),可以分兩步實現(xiàn)同樣的函數(shù)功能:
首先使用=>來替代關(guān)鍵詞function
var sum = (x, y) => { return x + y }
這個特性非常好?。?!
前面我們已經(jīng)說過用=>來替代關(guān)鍵詞function就意味著不會寫錯function了,這真是一個絕妙的設(shè)計思想!
其次,函數(shù)體只有一條返回語句時, 我們可以省略括號{}和return關(guān)鍵詞:
var sum = (x, y) => x + y
再夸張一點點,如果只有一個參數(shù)時,()可省略。
這是箭頭函數(shù)最簡潔的形式,常用于作用簡單的處理函數(shù),比如過濾:
// 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"]
箭頭函數(shù)的主要使用模式如下:
// 一個參數(shù)對應(yīng)一個表達式 param => expression;// 例如 x => x+2; // 多個參數(shù)對應(yīng)一個表達式 (param [, param]) => expression; //例如 (x,y) => (x + y); // 一個參數(shù)對應(yīng)多個表示式 param => {statements;} //例如 x = > { x++; return x;}; // 多個參數(shù)對應(yīng)多個表達式 ([param] [, param]) => {statements} // 例如 (x,y) => { x++;y++;return x*y;}; //表達式里沒有參數(shù) () => 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}
大家不要覺得好多啊,好麻煩,其實這些根本不復(fù)雜。投入一次,受益終生。(怎么感覺我像賣保險的……),寫一兩次你就習慣新的寫法了。
2、箭頭函數(shù)中的 this
箭頭函數(shù)內(nèi)的this值繼承自外圍作用域。運行時它會首先到它的父作用域找,如果父作用域還是箭頭函數(shù),那么接著向上找,直到找到我們要的this指向。
我們先看一道經(jīng)典的關(guān)于this的面試題:
var name = "leo"; var teacher = { name: "大彬哥", showName: function () { function showTest() { alert(this.name); } showTest(); } }; teacher.showName();//結(jié)果是 leo,而我們期待的是大彬哥,這里this指向了window,我們期待指向teacher
大家知道,ES5中的this說好聽了叫"靈活",說不好聽就是瞎搞,特別容易出問題.而且面試還非常愛考,工作更不用說了,經(jīng)常給我們開發(fā)搗亂,出現(xiàn)不好調(diào)試的bug,用E箭頭函數(shù)解決這個問題就很得心應(yīng)手了。
var name = "leo"; var teacher = { name: "大彬哥", showName: function () { let showTest = ()=>alert(this.name); showTest(); } }; teacher.showName();
箭頭函數(shù)中的this其實是父級作用域中的this。箭頭函數(shù)引用了父級的變量詞法作用域就是一個變量的作用在定義的時候就已經(jīng)被定義好,當在本作用域中找不到變量,就會一直向父作用域中查找,直到找到為止。
由于this在箭頭函數(shù)中已經(jīng)按照詞法作用域綁定了,所以,用call或者apply調(diào)用箭頭函數(shù)時,無法對this進行綁定,即傳入的第一個參數(shù)被忽略:
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已經(jīng)在詞法層面完成了綁定,通過call或apply方法調(diào)用一個函數(shù)時,只是傳入了參數(shù)而已,對this并沒有什么影響 。因此,這個設(shè)計節(jié)省了開發(fā)者思考上下文綁定的時間。
3、箭頭函數(shù)的特性
3.1 箭頭函數(shù)沒有 arguments
箭頭函數(shù)不僅沒有this,常用的arguments也沒有。如果你能獲取到arguments,那它
一定是來自父作用域的。
function foo() { return () => console.log(arguments) } foo(1, 2)(3, 4) // 1,2
上例中如果箭頭函數(shù)有arguments,就應(yīng)該輸出的是3,4而不是1,2。
箭頭函數(shù)不綁定arguments,取而代之用rest參數(shù)…解決
var foo = (...args) => { return args } console.log(foo(1,3,56,36,634,6)) // [1, 3, 56, 36, 634, 6]
箭頭函數(shù)要實現(xiàn)類似純函數(shù)的效果,必須剔除外部狀態(tài)。我們可以看出,箭頭函數(shù)除了傳入的參數(shù)之外,真的在普通函數(shù)里常見的this、arguments、caller是統(tǒng)統(tǒng)沒有的!
如果你在箭頭函數(shù)引用了this、arguments或者參數(shù)之外的變量,那它們一定不是箭頭函數(shù)本身包含的,而是從父級作用域繼承的。
3.2 箭頭函數(shù)中不能使用 new
let Person = (name) => { this.name = name; }; let one = new Person("galler");
運行該程序,則出現(xiàn)TypeError: Person is not a constructor
3.3 箭頭函數(shù)可以與變量解構(gòu)結(jié)合使用。
const full = ({ first, last }) => first + " " + last; // 等同于 function full(person) { return person.first + " " + person.last; } full({first: 1, last: 5}) // "1 5"
3.4 箭頭函數(shù)沒有原型屬性
var foo = () => {}; console.log(foo.prototype) //undefined
由此可以看出箭頭函數(shù)沒有原型。
另一個錯誤是在原型上使用箭頭函數(shù),如:
function A() { this.foo = 1 } A.prototype.bar = () => console.log(this.foo) let a = new A() a.bar() //undefined
同樣,箭頭函數(shù)中的this不是指向A,而是根據(jù)變量查找規(guī)則回溯到了全局作用域。同樣,使用普通函數(shù)就不存在問題。箭頭函數(shù)中不可加new,也就是說箭頭函數(shù)不能當構(gòu)造函數(shù)進行使用。
3.5 箭頭函數(shù)不能換行
var func = () => 1; // SyntaxError: expected expression, got "=>"
如果開發(fā)中確實一行搞不定,邏輯很多,就加{},你就想怎么換行怎么換行了。
var func = ()=>{ return "來?。』ハ鄠Π?!"; // 1.加{} 2.加return }
4、箭頭函數(shù)使用場景
JavaScript中this的故事已經(jīng)是非常古老了,每一個函數(shù)都有自己的上下文。
以下例子的目的是使用jQuery來展示一個每秒都會更新的時鐘:
$(".time").each(function () { setInterval(function () { $(this).text(Date.now()); }, 1000); });
當嘗試在setInterval的回調(diào)中使用this來引用DOM元素時,很不幸,我們得到的只是一個屬于回調(diào)函數(shù)自身
上下文的this。一個通常的解決辦法是定義一個that或者self變量:
$(".time").each(function () { var self = this; setInterval(function () { $(self).text(Date.now()); }, 1000); });
但當使用箭頭函數(shù)時,這個問題就不復(fù)存在了。因為它不產(chǎn)生屬于它自己上下文的this:
$(".time").each(function () { setInterval(() => $(this).text(Date.now()), 1000); });
箭頭函數(shù)的另一個用處是簡化回調(diào)函數(shù)。
// 正常函數(shù)寫法 [1,2,3].map(function (x) { return x * x; }); // 箭頭函數(shù)寫法 [1,2,3].map(x => x * x);
當然也可以在事件監(jiān)聽函數(shù)里使用:
document.body.addEventListener("click", event=>console.log(event, this)); // EventObject, BodyElement
5、總結(jié)
5.1 箭頭函數(shù)優(yōu)點
箭頭函數(shù)是使用=>語法的函數(shù)簡寫形式。這在語法上與 C#、Java 8 、Python( lambda 函數(shù))和 CoffeeScript 的
相關(guān)特性非常相似。
非常簡潔的語法,使用箭頭函數(shù)比普通函數(shù)少些動詞,如:function或return。
() => { ... } // 零個參數(shù)用 () 表示。 x => { ... } // 一個參數(shù)可以省略 ()。 (x, y) => { ... } // 多參數(shù)不能省略 ()。 如果只有一個return,{}可以省略。
更直觀的作用域和 this的綁定,它能讓我們能很好的處理this的指向問題。箭頭函數(shù)加上let關(guān)鍵字的使用,將會讓我們javascript代碼上一個層次。
5.2 箭頭函數(shù)使用場景
箭頭函數(shù)適合于無復(fù)雜邏輯或者無副作用的純函數(shù)場景下,例如用在map、reduce、filter的回調(diào)函數(shù)定義
中,另外目前vue、react、node等庫,都大量使用箭頭函數(shù),直接定義function的情況已經(jīng)很少了。
各位同學(xué)在寫新項目的時候,要不斷的琢磨箭頭函數(shù)使用場景、特點,享受使用箭頭函數(shù)帶來的便利,這樣才能更快地成長。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/104201.html
摘要:正是因為它沒有,所以也就不能用作構(gòu)造函數(shù)。不可以當作構(gòu)造函數(shù),也就是說,不可以使用命令,否則會拋出一個錯誤。不可以使用對象,該對象在函數(shù)體內(nèi)不存在。 箭頭函數(shù) 在之前ES5的版本中,我們定義一個函數(shù)的形式如下: function a() { // do something…… } 但是在ES6中,則新增了箭頭函數(shù)的方式,ES6中允許使用箭頭(=>)來定義函數(shù)。 () => { ...
摘要:在這里,如果用箭頭函數(shù),可以這樣改寫箭頭函數(shù)并沒有自己的,所以事件處理函數(shù)的調(diào)用者并不受影響。比如,在需要動態(tài)上下文的場景中,使用箭頭函數(shù)需要格外地小心,這些場景包括對象的方法原型方法事件的回調(diào)構(gòu)造函數(shù)。 showImg(https://segmentfault.com/img/bVboce6?w=1304&h=734); 前言 年味兒漸散,收拾下心情,繼續(xù)敲代碼吧。 對于即將到來金三...
摘要:關(guān)于的學(xué)習總結(jié)昨天寫了第一篇,主要是關(guān)于變量聲明關(guān)鍵字和,新增類型以及模板字符串,今天準備寫第二篇,里面的函數(shù)部分,新增了箭頭函數(shù),參數(shù)以及參數(shù)默認值。,這次我們在調(diào)用函數(shù)大的時候,兩個參數(shù)全部傳遞了值,因此返回。 關(guān)于ES6的學(xué)習總結(jié),昨天寫了第一篇,主要是關(guān)于變量聲明關(guān)鍵字let和const,新增類型Symbol以及模板字符串,今天準備寫第二篇,ES6里面的函數(shù)部分,ES6新增了箭...
摘要:但是箭頭函數(shù)并沒有自己的其是繼承了外層執(zhí)行環(huán)境的,且不能改變,因此不能作為構(gòu)造函數(shù),此時,引擎會在報錯。不能作為事件的回調(diào)在中,事件的回調(diào)函數(shù)中,會動態(tài)的指向監(jiān)聽的對象,但是由于監(jiān)聽是一個全局函數(shù),所以箭頭函數(shù)的回調(diào)中指向。 箭頭函數(shù) es6中添加了函數(shù)新的定義語法——箭頭函數(shù),當有大于一個形參的時候,必須使用()代表部分參數(shù),函數(shù)體大于一行時,必須使用{}將函數(shù)體括起來,并使用ret...
摘要:注意因為箭頭函數(shù)內(nèi)部的是指向外層代碼塊的最近的,例中的函數(shù)的,所以我們可以通過改變外層代碼塊的的指向從而改變箭頭函數(shù)中的指向例中使用了函數(shù)的方法。 一、this關(guān)鍵字小測試 ES6箭頭函數(shù)體中的this指向哪里? 在回答這個問題之前先來揣揣你對this關(guān)鍵字的了解程度:(讓我們回到ES6之前)題: var obj = { a: function() { cons...
閱讀 2470·2021-09-22 16:01
閱讀 3218·2021-09-22 15:41
閱讀 1241·2021-08-30 09:48
閱讀 569·2019-08-30 15:52
閱讀 3390·2019-08-30 13:57
閱讀 1771·2019-08-30 13:55
閱讀 3745·2019-08-30 11:25
閱讀 823·2019-08-29 17:25