摘要:因為它不產生屬于它自己上下文的箭頭函數的另一個用處是簡化回調函數。箭頭函數使用場景箭頭函數適合于無復雜邏輯或者無副作用的純函數場景下,例如用在的回調函數定義中,另外目前等庫,都大量使用箭頭函數,直接定義的情況已經很少了。
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
let Person = (name) => { 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的情況已經很少了。
各位同學在寫新項目的時候,要不斷的琢磨箭頭函數使用場景、特點,享受使用箭頭函數帶來的便利,這樣才能更快地成長。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104201.html
摘要:正是因為它沒有,所以也就不能用作構造函數。不可以當作構造函數,也就是說,不可以使用命令,否則會拋出一個錯誤。不可以使用對象,該對象在函數體內不存在。 箭頭函數 在之前ES5的版本中,我們定義一個函數的形式如下: function a() { // do something…… } 但是在ES6中,則新增了箭頭函數的方式,ES6中允許使用箭頭(=>)來定義函數。 () => { ...
摘要:在這里,如果用箭頭函數,可以這樣改寫箭頭函數并沒有自己的,所以事件處理函數的調用者并不受影響。比如,在需要動態上下文的場景中,使用箭頭函數需要格外地小心,這些場景包括對象的方法原型方法事件的回調構造函數。 showImg(https://segmentfault.com/img/bVboce6?w=1304&h=734); 前言 年味兒漸散,收拾下心情,繼續敲代碼吧。 對于即將到來金三...
摘要:關于的學習總結昨天寫了第一篇,主要是關于變量聲明關鍵字和,新增類型以及模板字符串,今天準備寫第二篇,里面的函數部分,新增了箭頭函數,參數以及參數默認值。,這次我們在調用函數大的時候,兩個參數全部傳遞了值,因此返回。 關于ES6的學習總結,昨天寫了第一篇,主要是關于變量聲明關鍵字let和const,新增類型Symbol以及模板字符串,今天準備寫第二篇,ES6里面的函數部分,ES6新增了箭...
摘要:注意因為箭頭函數內部的是指向外層代碼塊的最近的,例中的函數的,所以我們可以通過改變外層代碼塊的的指向從而改變箭頭函數中的指向例中使用了函數的方法。 一、this關鍵字小測試 ES6箭頭函數體中的this指向哪里? 在回答這個問題之前先來揣揣你對this關鍵字的了解程度:(讓我們回到ES6之前)題: var obj = { a: function() { cons...
閱讀 2386·2021-09-22 16:01
閱讀 3152·2021-09-22 15:41
閱讀 1170·2021-08-30 09:48
閱讀 489·2019-08-30 15:52
閱讀 3323·2019-08-30 13:57
閱讀 1712·2019-08-30 13:55
閱讀 3648·2019-08-30 11:25
閱讀 757·2019-08-29 17:25