Lodash的學習筆記(一)有意思的API

最近在學習JS函數式編程相關的內容,因而詳細的翻看了Lodash的文檔,感到別有洞天。這裏把本身對一些API的使用和見解作個筆記記錄下。css

Array

_.head/_.last

例子:前端

_.head([1, 2, 3]);
// → 1

_.last([1, 2, 3]);
// → 3

分別能夠抽取數組第一個元素的值和最後一個元素的值。咋看之下以爲很無聊。可是跟下面兩個結合起來就厲害。編程

_.tail/_.initial

例子:數組

_.tail([1, 2, 3]);
// → [2, 3]

_.initial([1, 2, 3]);
// → [1, 2]

也如字面描述通常容易理解的函數。可是結合上面的兩個函數就產生很大能量。數據結構

首先看一個針對數組尾部特殊化處理的例子:app

let names=['fred', 'barney', 'pebbles'];

_.initial(names).join(', ') +
(_.size(names) > 1 ? ', & ' : '') + _.last(names);

// → 'fred, barney, & pebbles'

怎麼樣比簡單的寫for+if else優雅不少吧。接着咱們來看看遞歸求和:函數式編程

function sum(arr){
    return _.head(arr) ? 
    ( _.head(arr) + sum( _.tail(arr) ) ) :
    0;
}

Tips函數

1)其實好像數組均可以表現爲性能

[a, [b, [c .....]]]

而後再將其扁平化的結果。 是否是?因此結合這四個函數,不少數組遍歷的操做均可以改寫成遞歸的方式。雖然性能可能略差,可是可讀性反而更強了(並不是全部的遞歸都必定損耗性能,詳細能夠去了解下JIT優化)。學習

2)可是在ES6中,更推薦優先使用數組的解構。

_.zip

例子:

_.zip(['fred', 'barney'], [30, 40]);
// → [['fred', 30], ['barney', 40]]

_.zip(*array) 將幾個數組按照位置組成新的數組,返回數組列表。這個方法就有點像SQL裏面select兩個列的狀況。對重組數據結構很是有幫助。

_.unzip

既然lodash是個函數庫,那有zip確定也有他的逆運算unzip。這裏就不舉例了。unzip其實能夠看做對ES6數組解構的補充,應用的場景也是十分類似的。

Collection

_.map/_.reduce/_.filter

這三個函數其實早就名聲在外,就不舉例了。列出來只是爲了提醒,遍歷集合可不只僅只有_.each。任什麼時候候都優先考慮這些函數。

_.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 => ||

懂了吧。其實一樣也算是對_.each的擴充。還有他們都有條件短路的優化哦。

Function

_.curry

是函數柯里化的函數。不要問我爲何不是庫裏化。什麼是柯里化自行百度。
例子:

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個常見做用:1. 參數複用;2. 構建高階函數;3. 延遲計算。
參數複用的例子:

let parse = function(data, config){
    ……
    return ……;
};

let config = {};
let parseByConfig = _.curryRight(parse)(config);

如代碼所示,這是一個數據解析函數,經過某些配置按照必定的規則去解析數據。若是在某個場景下參數配置都同樣。那能夠用柯里化先引入一個參數。而後再接收不一樣的數據。這樣就不用在每次調用時都引入一樣的config參數。

剩下兩個特性一個等會講,一個不在本文討論範圍內。

_.partial

部分函數,我習慣這麼叫他,仍是先看例子。

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'

好像跟柯里化很像。是的,它其實就是柯里化的具體應用——構建高階函數。_.curry會把一個函數轉化成能夠柯里化函數,而當這個柯里化函數接受了必定的參數後,它就變成了一個部分應用函數了。

Seq

_.chain

這個是我認爲的lodash中最有意思的方法。

$('div').css('color','red')
    .on('click', function(){})
    .fadeIn();

做爲一個合格的前端攻城獅,你對這個必定不陌生。它必定給你帶來過不少美好的記憶。那咱們如何讓這樣一段優雅的代碼應用到非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();

兩段代碼在作同樣的事情。你更喜歡哪一個呢。不過要注意_.chain最後的value。由於_.chain用一個容器包裝了你的對象,最後須要經過value返回出真正的值。若是不能理解,聯想一下下面這段代碼:

$('div')[0].classList

用jQuery選擇器篩選到的是jQuery對象,而若是要調用真正的DOM對象的屬性的話,還要用索引去調用它。

Util

_.flow

function square(n) {
  return n * n;
}

var addSquare = _.flow(_.add, square);
addSquare(1, 2);
// → 9

這一樣是用來組合高階函數的一個方法。若是用數學的角度去思考的話,就有點像, 把函數 f(), g(), 和h() 組合起來能夠獲得複合函數 f( g( h() ) )。

相關文章
相關標籤/搜索