作者:Sequoia McDowell
創(chuàng)新互聯(lián)主營鄯善網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,App定制開發(fā),鄯善h5小程序開發(fā)搭建,鄯善網(wǎng)站營銷推廣歡迎鄯善等地區(qū)企業(yè)咨詢
2016年01月16日
ES6來啦!隨著越來越多的代碼庫和思潮引領者開始在他們的代碼中使用ES6,以往被認為是“僅需了解”的ES6特性變成了必需的代碼常識。這不僅僅是新的語法學習 - 在許多范例中, ES6中新的語言特性可以讓在ES5中寫起來非常麻煩的表達變得更加簡單,進而鼓勵了新表達方式的使用。下面我們將關注一個這樣簡潔表達的使用范例:ES6中的箭頭函數(shù)如何使高階函數(shù)的書寫更加簡便。
高階函數(shù)是至少具有以下兩種功能之一的函數(shù):
使用一個或多個函數(shù)作為實參
返回一個函數(shù)作為結果
本文的目的并不是說服你立即采用這種新方式,盡管筆者非常鼓勵你嘗試使用!本文旨在讓你熟悉這種表達方式,這樣當你在遇到其他人基于ES6寫的代碼庫時,不會如筆者當初一樣看著這些陌生代碼撓頭不解。如果你在此之前需要先復習一下箭頭語法的知識,請先查閱這篇文章。
希望你熟悉有返回值的箭頭函數(shù):
const square = x => x * x;
但是下面這兩行代碼是什么意思?
const has = p => o => o.hasOwnProperty(p); const sortBy = p => (a, b) => a[p] > b[p];
“p 返回 o 返回 o.hasOwnProperty…”這句代碼是什么意思?我們能這樣用嗎?
為了說明帶箭頭的高階函數(shù)的書寫規(guī)則,讓我們一起來看一個經(jīng)典示例:加法函數(shù)。在ES5中會這樣寫:
function add(x){ return function(y){ return y + x; }; } var addTwo = add(2); addTwo(3); // => 5 add(10)(11); // => 21
我們的加法函數(shù)輸入x,返回了一個輸入y返回值是y + x的函數(shù)。那我們應該如何用箭頭函數(shù)表達這個函數(shù)呢?已知...
箭頭函數(shù)定義是一個表達式,并且
箭頭函數(shù)隱式返回單一表達式結果
那么我們所要做的就是讓另一個箭頭函數(shù)作為我們箭頭函數(shù)的函數(shù)體,因此表達方式如下:
const add = x => y => y + x; // outer function: x => [inner function, uses x] // inner function: y => y + x;
現(xiàn)在我們就可以通過一個與變量x相關的返回值創(chuàng)建內部函數(shù):
const add2 = add(2);// returns [inner function] where x = 2 add2(4); // returns 6: exec inner with y = 4, x = 2 add(8)(7); // 15
我們所寫的加法函數(shù)并不是超級有用,但是它可以說明一個外函數(shù)如何輸入一個以x為變量的參數(shù)函數(shù),并在它返回的函數(shù)中引用此函數(shù)。
假如你在github上看到了一個ES6代碼庫,并且遇到了下面這樣的代碼:
const has = p => o => o.hasOwnProperty(p); const sortBy = p => (a, b) => a[p] > b[p]; let result; let users = [ { name: 'Qian', age: 27, pets : ['Bao'], title : 'Consultant' }, { name: 'Zeynep', age: 19, pets : ['Civelek', 'Muazzam'] }, { name: 'Yael', age: 52, title : 'VP of Engineering'} ]; result = users .filter(has('pets')) .sort(sortBy('age'));
這些代碼又是什么意思?我們叫它箭頭原型的排列和濾波方法,每一種方法都使用一個單功能參數(shù),但是我們會調用返回函數(shù)的函數(shù)來篩選和排序,而不是編寫表達式去做這些。
讓我們來看一看,在下列每種情況下返回函數(shù)的表達方式。
result = users .filter(x => x.hasOwnProperty('pets')) //pass Function to filter .sort((a, b) => a.age > b.age); //pass Function to sort
result = users .filter(has('pets')) //pass Function to filter .sort(sortBy('age')); //pass Function to sort
在每個實例中,過濾過程都是通過檢查對象是否含有名為“pets”的屬性值的函數(shù)執(zhí)行的。
它的有效性出于以下幾個原因:
它減少了重復代碼
它簡化了代碼的可重用性
它提升了代碼含義的清晰度
想象一下我們只想過濾出有寵物和有職位的用戶,我們可以在其中添加另一個函數(shù):
result = users .filter(x => x.hasOwnProperty('pets')) .filter(x => x.hasOwnProperty('title')) ...
這里的重復只是徒增雜亂:它的簡明度沒有提升,只是寫了更多代碼妨礙視線。下面是可實現(xiàn)同樣功能的使用了has函數(shù)的代碼:
result = users .filter(has('pets')) .filter(has('title')) ...
這段代碼更加短小精悍且易于書寫,還可以減少打錯字的情況。筆者同時認為這段代碼大大增加了閱讀清晰度,一眼就能讀出代碼的含義。
至于函數(shù)重用性,如果需要在很多地方過濾出有寵物的用戶或者有職位的用戶,你可以創(chuàng)建如下函數(shù),并按需重用:
const hasPets = has('pets'); const isEmployed = has('title'); const byAge = sortBy('age'); let workers = users.filter(isEmployed); let petOwningWorkers = workers.filter(hasPets); let workersByAge = workers.sort(byAge);
我們也可以使用已給出的函數(shù)來獲得單返回值,并不僅僅是用于過濾數(shù)組:
let user = {name: 'Assata', age: 68, title: 'VP of Operations'}; if(isEmployed(user)){ // true //do employee action } hasPets(user); // false has('age')(user); //true
讓我們來寫一個能檢查對象擁有一個有固定值的主鍵的過濾函數(shù)。has函數(shù)可檢查主鍵,然而我們需要知道兩項值(主鍵和鍵值),而不是一項,來同時檢查值。下面請看一種方法:
//[p]roperty, [v]alue, [o]bject: const is = p => v => o => o.hasOwnProperty(p) && o[p] == v; // broken down: // outer: p => [inner1 function, uses p] // inner1: v => [inner2 function, uses p and v] // inner2: o => o.hasOwnProperty(p) && o[p] = v;
此處,叫做“is”的函數(shù)可執(zhí)行以下三件事:
取一個屬性名并且返回一個函數(shù),該函數(shù)……
取一個函數(shù)值返回一個函數(shù),該函數(shù)……
取一個對象,并檢測該對象是否有特定函數(shù)值的特定屬性,最終返回一個布爾值。
下面是一個使用is函數(shù)來過濾用戶的示例:
const titleIs = is('title'); // titleIs == v => o => o.hasOwnProperty('title') && o['title'] == v; const isContractor = titleIs('Contractor'); // isContractor == o => o.hasOwnProperty('contractor') && o['title'] == 'Contractor'; let contractors = users.filter(isContractor); let developers = users.filter(titleIs('Developer')); let user = {name: 'Viola', age: 50, title: 'Actress', pets: ['Zak']}; isEmployed(user); // true isContractor(user); // false
看一眼下面這個函數(shù),記下你弄清楚函數(shù)意義的時間:
const i = x => y => z => h(x)(y) && y[x] == z;
現(xiàn)在請再看一下同功能僅在書寫風格中略微不同的函數(shù):
const is = prop => val => obj => has(prop)(obj) && obj[prop] == val;
可見,書寫一行越簡潔越好的函數(shù)的編碼趨勢是以犧牲可讀性為代價的。請克制自己這樣做的沖動!簡短卻無意義的變量名的確看起來很漂亮,但是讓人難以理解函數(shù)的功能。起一個包含多個詞的有意義的變量名和函數(shù)名,其實是在幫你自己和同事理解函數(shù)功能。
如果你想以年齡降序排序而不是升序排列,該怎么做呢?或者說查找不是雇員的用戶該怎么做呢?我們需要去寫一個新的functionssortByDesc 或者notHas程序嗎?當然不用!我們可以將已有的返回布爾值的函數(shù)封裝起來,用一個反轉其布爾值的函數(shù)來實現(xiàn)上述功能,反之亦然。
//take args, pass them thru to function x, invert the result of x const invert = x => (...args) => !x(...args); const noPets = invert(hasPets); let petlessUsersOldestFirst = users .filter(noPets) .sort(invert(sortBy('age')));
函數(shù)式編程在編程界的勢頭越來越強勁,而ES6使得在JavaScript中采用這種編程思想更加容易。如果你在JavaScript編程過程中還沒遇到過函數(shù)式編程風格的代碼,你很可能在接下來的幾個月里就能遇到。這意味著即便你不喜歡這種風格,理解它的基礎知識也是非常重要的,有的知識在這里已經(jīng)提到過了。希望這篇文章提出的概念能夠幫你在實際遇到ES6代碼時準備好前提知識,更希望它能鼓勵你嘗試這種編程風格!
OneAPM 助您輕松鎖定 .NET 應用性能瓶頸,通過強大的 Trace 記錄逐層分析,直至鎖定行級問題代碼。以用戶角度展示系統(tǒng)響應速度,以地域和瀏覽器維度統(tǒng)計用戶使用情況。想閱讀更多技術文章,請訪問 OneAPM 官方博客。
本文轉自 OneAPM 官方博客
原文鏈接:https://strongloop.com/strongblog/higher-order-functions-in-es6easy-as-a-b-c/
+
當前題目:ES6中的高階函數(shù):如同a=>b=>c一樣簡單
瀏覽路徑:http://muchs.cn/article4/gddsoe.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、云服務器、關鍵詞優(yōu)化、小程序開發(fā)、ChatGPT、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)