摘要:是函數(shù)柯里化的函數(shù)。例子柯里化有個(gè)常見作用參數(shù)復(fù)用構(gòu)建高階函數(shù)延遲計(jì)算。是的,它其實(shí)就是柯里化的具體應(yīng)用構(gòu)建高階函數(shù)。這個(gè)是我認(rèn)為的中最有意思的方法。不過要注意最后的。這同樣是用來組合高階函數(shù)的一個(gè)方法。
最近在學(xué)習(xí)JS函數(shù)式編程相關(guān)的內(nèi)容,于是詳細(xì)的翻看了Lodash的文檔,感到別有洞天。這里把自己對一些API的使用和看法做個(gè)筆記記錄下。
Array _.head/_.last例子:
_.head([1, 2, 3]); // → 1 _.last([1, 2, 3]); // → 3
分別可以抽取數(shù)組第一個(gè)元素的值和最后一個(gè)元素的值。咋看之下覺得很無聊。但是跟下面兩個(gè)結(jié)合起來就厲害。
_.tail/_.initial例子:
_.tail([1, 2, 3]); // → [2, 3] _.initial([1, 2, 3]); // → [1, 2]
也如字面描述一般容易理解的函數(shù)。但是結(jié)合上面的兩個(gè)函數(shù)就產(chǎn)生很大能量。
首先看一個(gè)針對數(shù)組尾部特殊化處理的例子:
let names=["fred", "barney", "pebbles"]; _.initial(names).join(", ") + (_.size(names) > 1 ? ", & " : "") + _.last(names); // → "fred, barney, & pebbles"
怎么樣比簡單的寫for+if else優(yōu)雅很多吧。接著我們來看看遞歸求和:
function sum(arr){ return _.head(arr) ? ( _.head(arr) + sum( _.tail(arr) ) ) : 0; }
Tips
1)其實(shí)好像數(shù)組都可以表現(xiàn)為
[a, [b, [c .....]]]
然后再將其扁平化的結(jié)果。 是不是?所以結(jié)合這四個(gè)函數(shù),很多數(shù)組遍歷的操作都可以改寫成遞歸的方式。雖然性能可能略差,但是可讀性反而更強(qiáng)了(并非所有的遞歸都一定損耗性能,詳細(xì)可以去了解下JIT優(yōu)化)。
2)但是在ES6中,更推薦優(yōu)先使用數(shù)組的解構(gòu)。
_.zip例子:
_.zip(["fred", "barney"], [30, 40]); // → [["fred", 30], ["barney", 40]]
_.zip(*array) 將幾個(gè)數(shù)組按照位置組成新的數(shù)組,返回?cái)?shù)組列表。這個(gè)方法就有點(diǎn)像SQL里面select兩個(gè)列的情況。對重組數(shù)據(jù)結(jié)構(gòu)非常有幫助。
_.unzip既然lodash是個(gè)函數(shù)庫,那有zip肯定也有他的逆運(yùn)算unzip。這里就不舉例了。unzip其實(shí)可以看作對ES6數(shù)組解構(gòu)的補(bǔ)充,應(yīng)用的場景也是十分相似的。
Collection _.map/_.reduce/_.filter這三個(gè)函數(shù)其實(shí)早就名聲在外,就不舉例了。列出來只是為了提醒,遍歷集合可不僅僅只有_.each。任何時(shí)候都優(yōu)先考慮這些函數(shù)。
_.every/_.some例子:
let users = [ { "user": "barney", "active": true }, { "user": "fred", "active": false } ]; _.every(users, { "user": "barney", "active": false }); // → false _.some(users, ["active", false]); // → true
什么?看不懂?
_.every => && _.some => ||
懂了吧。其實(shí)同樣也算是對_.each的擴(kuò)充。還有他們都有條件短路的優(yōu)化哦。
Function _.curry是函數(shù)柯里化的函數(shù)。不要問我為什么不是庫里化。什么是柯里化自行百度。
例子:
let abc = function(a, b, c) { return [a, b, c]; }; let curried = _.curry(abc); curried(1)(2)(3); // → [1, 2, 3] curried(1, 2)(3); // → [1, 2, 3] curried(1, 2, 3); // → [1, 2, 3] // Curried with placeholders. curried(1)(_, 3)(2); // → [1, 2, 3]
柯里化有3個(gè)常見作用:1. 參數(shù)復(fù)用;2. 構(gòu)建高階函數(shù);3. 延遲計(jì)算。
參數(shù)復(fù)用的例子:
let parse = function(data, config){ …… return ……; }; let config = {}; let parseByConfig = _.curryRight(parse)(config);
如代碼所示,這是一個(gè)數(shù)據(jù)解析函數(shù),通過某些配置按照一定的規(guī)則去解析數(shù)據(jù)。如果在某個(gè)場景下參數(shù)配置都一樣。那可以用柯里化先引入一個(gè)參數(shù)。然后再接收不同的數(shù)據(jù)。這樣就不用在每次調(diào)用時(shí)都引入同樣的config參數(shù)。
剩下兩個(gè)特性一個(gè)等會講,一個(gè)不在本文討論范圍內(nèi)。
_.partial部分函數(shù),我習(xí)慣這么叫他,還是先看例子。
let greet = function(greeting, name) { return greeting + " " + name; }; let sayHelloTo = _.partial(greet, "hello"); sayHelloTo("fred"); // → "hello fred" // Partially applied with placeholders. let greetFred = _.partial(greet, _, "fred"); greetFred("hi"); // → "hi fred" let greet = function(greeting, name) { return greeting + " " + name; }; let sayHelloTo = _.partial(greet, "hello"); sayHelloTo("fred"); // → "hello fred" // Partially applied with placeholders. let greetFred = _.partial(greet, _, "fred"); greetFred("hi"); // → "hi fred"
好像跟柯里化很像。是的,它其實(shí)就是柯里化的具體應(yīng)用——構(gòu)建高階函數(shù)。_.curry會把一個(gè)函數(shù)轉(zhuǎn)化成可以柯里化函數(shù),而當(dāng)這個(gè)柯里化函數(shù)接受了一定的參數(shù)后,它就變成了一個(gè)部分應(yīng)用函數(shù)了。
Seq _.chain這個(gè)是我認(rèn)為的lodash中最有意思的方法。
$("div").css("color","red") .on("click", function(){}) .fadeIn();
作為一個(gè)合格的前端攻城獅,你對這個(gè)一定不陌生。它一定給你帶來過很多美好的記憶。那我們?nèi)绾巫屵@樣一段優(yōu)雅的代碼應(yīng)用到非DOM對象上呢。用_.chain就行了。
_.head( _.map( _.sortBy("users", "age"), function(o) { return `${o.user} is ${o.age}`; } ) ) _.chain(users) .sortBy("age") .map(function(o) { return o.user + " is " + o.age; }) .head() .value();
兩段代碼在做一樣的事情。你更喜歡哪個(gè)呢。不過要注意_.chain最后的value。因?yàn)?b>_.chain用一個(gè)容器包裝了你的對象,最后需要通過value返回出真正的值。如果不能理解,聯(lián)想一下下面這段代碼:
$("div")[0].classList
用jQuery選擇器篩選到的是jQuery對象,而如果要調(diào)用真正的DOM對象的屬性的話,還要用索引去調(diào)用它。
Util _.flowfunction square(n) { return n * n; } var addSquare = _.flow(_.add, square); addSquare(1, 2); // → 9
這同樣是用來組合高階函數(shù)的一個(gè)方法。如果用數(shù)學(xué)的角度去思考的話,就有點(diǎn)像, 把函數(shù) f(), g(), 和h() 組合起來可以得到復(fù)合函數(shù) f( g( h() ) )。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/79387.html
摘要:例如現(xiàn)在的入門學(xué)習(xí)手記系列。收到粉絲留言和打賞的喜悅。安裝上一篇入門學(xué)習(xí)手記一,主要是介紹了的核心概念,是整個(gè)學(xué)習(xí)過程的基礎(chǔ)知識。新生成的類似如下入門學(xué)習(xí)手記因?yàn)樯傻膬?nèi)容過多,我直接省略掉了。 showImg(https://segmentfault.com/img/bVbk5Nd?w=1150&h=599); 本人微信公眾號:前端修煉之路,歡迎關(guān)注。 最近開始想要維護(hù)一個(gè)個(gè)人的公眾...
摘要:中文文檔目前我只找到了版本,現(xiàn)在已經(jīng)更新到了,好多文檔已經(jīng)過期。而且中太多,有時(shí)候常用的幾個(gè)我總是記不住名字,在這里貼出來,方便自己和大家。原生用法直接使用的根據(jù)條件去除某個(gè)元素。 lodash中文文檔目前我只找到了3.10.x版本,現(xiàn)在lodash已經(jīng)更新到4.17.x了,好多文檔已經(jīng)過期。而且lodash中api太多,有時(shí)候常用的幾個(gè)我總是記不住名字,在這里貼出來,方便自己和大家。...
摘要:文檔地址中文文檔英文文檔源碼地址第一個(gè)函數(shù)是,不過源碼中依賴了,所以第一篇文章就從開始。這個(gè)函數(shù)的作用就是裁剪數(shù)組,從下標(biāo)開始,到下標(biāo)結(jié)束,但是并不包含,并將結(jié)果作為一個(gè)數(shù)組返回。并且注明了這個(gè)方法用于代替來確保數(shù)組正確返回。 百忙之中(閑來無事)想抽點(diǎn)時(shí)間好好讀一下源碼,于是就選了Lodash來寫一個(gè)系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源...
摘要:文檔地址中文文檔英文文檔源碼地址將數(shù)組拆分成多個(gè)長度的區(qū)塊,并將這些區(qū)塊組成一個(gè)新數(shù)組。如果無法被分割成全部等長的區(qū)塊,那么最后剩余的元素將組成一個(gè)區(qū)塊。 百忙之中(閑來無事)想抽點(diǎn)時(shí)間好好讀一下源碼,于是就選了Lodash來寫一個(gè)系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源碼地址:gayhub _.chunk(array, [size...
摘要:文檔地址中文文檔英文文檔源碼地址創(chuàng)建一個(gè)新數(shù)組,包含原數(shù)組中所有的非假值元素。例如和都是被認(rèn)為是假值。下面對比一下兩者效率,如下圖傳送門可以看到使用更快,如果沒有兼容性需求,還是使用原生函數(shù)比較好。 百忙之中(閑來無事)想抽點(diǎn)時(shí)間好好讀一下源碼,于是就選了Lodash來寫一個(gè)系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源碼地址:gayhub ...
閱讀 811·2021-11-23 09:51
閱讀 2523·2021-10-11 11:10
閱讀 1395·2021-09-23 11:21
閱讀 1179·2021-09-10 10:50
閱讀 950·2019-08-30 15:54
閱讀 3389·2019-08-30 15:53
閱讀 3348·2019-08-30 15:53
閱讀 3261·2019-08-29 17:23