摘要:在現代中最讓人期待的特性就是關于箭頭函數,用來標識。比如,受歡迎的庫會強制使用箭頭函數創建匿名函數。然而,箭頭函數有優點,也有一些缺點。下面就從為何用怎么用何時用,這個三部分做一些總結。因此,箭頭函數不能用作生成器。
在現代JS中最讓人期待的特性就是關于箭頭函數,用=>來標識。箭頭函數有兩個主要的優點:
更簡短的函數;
更直觀的作用域和this的綁定(不綁定this)
因為這些優點,箭頭函數比起其他形式的函數聲明更受歡迎。比如,受歡迎的airbnb eslint configuration庫會強制使用JavaScript箭頭函數創建匿名函數。
然而,箭頭函數有優點,也有一些“缺點”。這就需要在使用的時候做一些權衡。下面就從為何用、怎么用、何時用,這個三部分做一些總結。
引入箭頭函數有兩個方面的作用:更簡短的函數并且不綁定this更簡短的函數
var elements = ["h1", "div", "span", "section"]; elements.map(function(el) { return el.length; // 返回數組: [2, 3, 4, 7] }); // 從上面的普通函數可以改寫為如下的箭頭函數 elements.map((el) => { return el.length; // [2, 3, 4, 7] }); // 當箭頭函數只有一個參數時,可以省略參數的圓括號 elements.map(el => { return el.length; // [2, 3, 4, 7] }); // 當箭頭函數體只有一個`return`語句時,可以省略`return`關鍵字和方法體的花括號 elements.map(el => el.length); // [2, 3, 4, 7] // 在這個例子中,因為我們只需要`length`屬性,所以可以使用參數結構 // 需要注意的是字符串`"length"`是我們想要獲得的屬性名稱,而`elLength`則只是個變量名,可以替換成任意合法的變量名 elements.map(({ "length": elLength }) => elLength); // [2, 3, 4, 7]不綁定this
在箭頭函數出現之前,每個新定義的函數都有它自己的this值(在構造函數的情況下是一個新對象,在嚴格模式的函數調用中則為undefined,如果該函數被作為"對象方法"調用則為基礎對象等)。
而箭頭函數并沒有它自己的執行上下,實際上,這就意味著代碼中的this和arguments都是繼承它的父函數。
const obj = { name: "test object", createAnonFunction: function() { return function() { console.log(this.name); return this; } }, createArrowFunction: function() { return () => { console.log(this.name); return this; } } } const anon = obj.createAnonFunction(); anon(); // undefined anon() === window // true const arrow = obj.createArrowFunction(); arrow(); // "test object" arrow() === obj // true
第一個匿名參數有自己的上下文(指向的并非obj對象),當被賦值給anon變量且調用時,this發生了改變,指向了window。另一個,箭頭函數與創建它的函數有相同的上下文,故指向obj對象。
通過call或者apply調用由于箭頭函數沒有自己的this指針,通過call()或者apply()方法調用一個函數時,只能傳遞參數(不能綁定this),它們的第一個參數會被忽略。
var adder = { base: 1, add: function(a) { var f = v => v + this.base; return f(a); }, addByCall: function(a) { var f = v => v + this.base; var b = { base: 2 }; return f.call(b, a) } } adder.add(1); // 2 adder.addByCall(1); // 2不綁定arguments
箭頭函數不綁定Arguments對象。因此,在本示例中,arguments只是引用了封閉作用域內的arguments:
function foo(n) { var f = () => arguments[0] + n; // 隱式綁定 foo 函數的arguments對象,arguments[0]是 n return f(); } foo(1); // 2
在大多數情況下,使用剩余參數是相對使用arguments對象的更好選擇。
function foo(arg) { var f = (...agrs) => args[0]; return f(arg); } foo(1); // 1 function foo(arg1, arg2) { var f = (...args) => args[1]; return f(arg1, arg2); } foo(1, 2); // 2怎么用? 優化代碼
比如你有一個有值的數組,你想去map遍歷每一項,這時箭頭函數就非常推薦:
const words = ["hello", "WORLD", "Whatever"]; const downcasedWords = words.map(word => word.toLowerCase());
一個及其常見的例子就是返回一個對象的某個值:
const names = objects.map(object => object.name);
類似的,當用forEach來替換傳統for循環的時候,實際上箭頭函數會直觀的保持this來自于父一級:
this.examples.forEach(example => { this.runExample(example); });Promise和Promise鏈
當在編寫異步編程時,箭頭函數也會讓代碼更加直觀和簡潔。
這是箭頭函數的理想位置,特別是如果您生成的函數是有狀態的,同時想引用對象中的某些內容。
this.doSomethingAsync().then((result) => { this.storeResult(result); });對象轉換
箭頭函數的另一個常見而且十分有用的地方就是用于封裝的對象轉換。
例如在Vue.js中,有一種通用模式,就是使用mapState將Vuex存儲的各個部分,直接包含到Vue組件中。
這涉及到定義一套mappers,用于從原對象到完整的轉換輸出,這在組件問題中實十分有必要的。這一系列簡單的轉換,使用箭頭函數是最合適不過的。比如:
export default { computed: { ...mapState([ "results", "users" ]) } }何時用?(不推薦使用場景) 使用new操作符
箭頭函數不能用作構造器,和new一起使用會拋出錯誤。
var Foo = () => {}; var foo = new Foo(); // TypeError: Foo is not a constructor使用prototype屬性
箭頭函數沒有prototype屬性。
var Foo = () => {}; console.log(Foo.prototype); // undefined使用yield關鍵字
yield 關鍵字通常不能在箭頭函數中使用(除非是嵌套在允許使用的函數內)。因此,箭頭函數不能用作生成器。
深層調用如果你將函數定義為箭頭函數,并且在他們之間來回調用,當你調試bug的時候你將被代碼困惑,甚至得到如下的錯誤信息:
{anonymous}(){anonymous}(){anonymous}(){anonymous}(){anonymous}() //anonymous常見錯誤 返回對象字面量
記住用params => { object: literal }這種簡單的語法返回對象字面量是行不通的。
var func = () => { foo: 1 }; func(); // undefined var func = () => { foo: function() {} }; // SyntaxError: function statement requires a name
這是因為花括號{}里面的代碼被解析為一系列語句(即 foo 被認為是一個標簽,而非對象字面量的組成部分)。
所以,記得用圓括號把對象字面量包起來:
var func = () => ({foo: 1});換行
箭頭函數在參數和箭頭之間不能換行。
var func = () => 1; // SyntaxError: expected expression, got "=>"解析順序
雖然箭頭函數中的箭頭不是運算符,但箭頭函數具有與常規函數不同的特殊運算符優先級解析規則。
let callback; callback = callback || function() {}; // ok callback = callback || () => {}; // SyntaxError: invalid arrow-function arguments callback = callback || (() => {}); // ok更多示例 使用三元運算符
var foo = a => a > 15 ? 15 : a; foo(10); // 10 foo(16); // 15閉包
// 標準的閉包函數 function Add() { var i = 0; return function() { return (++i); } } var add = Add(); add(); // 1 add(); // 2 // 箭頭函數體的閉包(i = 0是默認參數) var Add = (i = 0) => { return (() => (++i)) }; var add = Add(); add(); // 1 add(); // 2 // 因為僅有一個返回,return及括號也可以省略 var Add = (i = 0) => () => (++i);箭頭函數遞歸
var fact = (x) => ( x == 0 ? 1 : x*fact(x-1) ); fact(5); // 120總結
箭頭函數是JS語言中十分特別的屬性,并且使很多情形中代碼更加的變化莫測。盡管如此,就像其他的語言特性,他們有各自的優缺點。因此我們使用它應該僅僅是作為一種工具,而不是無腦的簡單的全部替換為箭頭函數。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/110033.html
摘要:以上是面試中筆試涉及到的知識點或者后面被問到的只是點。也許是根據薪資和面試的等級來出題的。我剛面試完回家,吃了一個泡面,回憶下面試題。同時作為傳遞到構造函數,執行了一次讓構造函數里面的屬性和方法賦值了一份給。 css 如何水平垂直居中,請盡量多說幾種方法?很尷尬,我多次面試都被問到這個問題,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...
摘要:以上是面試中筆試涉及到的知識點或者后面被問到的只是點。也許是根據薪資和面試的等級來出題的。我剛面試完回家,吃了一個泡面,回憶下面試題。同時作為傳遞到構造函數,執行了一次讓構造函數里面的屬性和方法賦值了一份給。 css 如何水平垂直居中,請盡量多說幾種方法?很尷尬,我多次面試都被問到這個問題,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...
摘要:的網站仍然使用有漏洞庫上周發布了開源社區安全現狀報告,發現隨著開源社區的日漸活躍,開源代碼中包含的安全漏洞以及影響的范圍也在不斷擴大。與應用安全是流行的服務端框架,本文即是介紹如何使用以及其他的框架來增強應用的安全性。 showImg(https://segmentfault.com/img/remote/1460000012181337?w=1240&h=826); 前端每周清單專注...
摘要:前端知識點總結高級持續更新中字符串什么是連續存儲多個字符的字符數組相同下標遍歷選取不同類型不同不通用所有字符串都無權修改原字符串,總是返回新字符串大小寫轉換統一轉大寫統一轉小寫何時不區分大小寫時,都需要先轉為一致的大小寫,再比較。 前端知識點總結——JS高級(持續更新中) 1.字符串 什么是: 連續存儲多個字符的字符數組 相同: 1. 下標 2. .length 3. 遍歷 4....
摘要:其次,指向有一個好處,構造函數一般不要直接運行,那要是強行運行呢指向會給添加許多屬性,有擾亂命名空間之嫌,指向之后,你強行運行我就強行報錯會給增加屬性,改成嚴格模式就會當然,不能解決所有問題,所以有了箭頭函數參考嚴格模式詳解 上github看原文:點一下 系列 一日,見use strict,冥想許久…… 系列列表:從use strict看JS(一):this與箭頭函數從use stri...
閱讀 1107·2021-11-24 10:24
閱讀 2594·2021-11-22 13:54
閱讀 1000·2021-09-24 09:55
閱讀 3603·2019-08-30 15:54
閱讀 1318·2019-08-30 15:44
閱讀 1096·2019-08-30 14:23
閱讀 3203·2019-08-29 13:45
閱讀 1284·2019-08-29 11:19