2018-05-26 經(jīng)常用到的lodash 函數(shù)

lodash的官方文檔: https://lodash.com/docs/4.17.10
lodash的中文文檔: http://lodash.think2011.net/keys
所有的方法,根據(jù)操作對(duì)象的不同被放到了不同的目錄下,比如當(dāng)你想處理一個(gè)數(shù)組的時(shí)候,與其開(kāi)始著手寫個(gè)方法,不如到lodash的array目錄下找找有沒(méi)有可以用的方法,避免造重復(fù)的車輪,而且處處可用,很方便。

image.png

下面是我常用的一些方法,歸納出來(lái),其實(shí)都很基礎(chǔ),只是記錄下來(lái)。例子大部分來(lái)自官網(wǎng)。BTW, 這里我只簡(jiǎn)單的記下用到的方法,參數(shù)寫的可能不規(guī)范,主要是后面的使用場(chǎng)景和方法。建議大家先看一下官方文檔。
lodash引入的時(shí)候一般都用表示。不知道為什么有些 發(fā)布之后就丟掉了。
var _=require("lodash")

--collection操作--

.isEmpty(value) , Checks if value is an empty object, collection, map, or set.
.orderBy(collection, [iteratees=[.identity]], [orders]) 和
.sortBy()相比, 這個(gè)方法功能更多,可以選擇根據(jù)collection的某個(gè)字段按照升序或者降序排列。例子

var users = [
  { 'user': 'fred',   'age': 48 },
  { 'user': 'barney', 'age': 34 },
  { 'user': 'fred',   'age': 40 },
  { 'user': 'barney', 'age': 36 }
];
 
// Sort by `user` in ascending order and by `age` in descending order.
_.orderBy(users, ['user', 'age'], ['asc', 'desc']);
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
再如,按時(shí)間降序排序
_.orderBy(pickTask.pullResults, "pulledWhen", "desc");

.map(collection, [iteratee=.identity]), 從數(shù)組對(duì)象中映射出某個(gè)值來(lái)

如,取出OrderId: _.map(requestInputList, input => input.OrderId)

.filter(collection, [predicate=.identity]),從數(shù)組對(duì)象中過(guò)濾出某些符合條件的對(duì)象來(lái)
_.find(collection, function), 返回符合條件的第一個(gè)元素

_.find(itemFieldViews, field => propertyName === field.propertyName);

_.size(collection) 得出這個(gè)數(shù)組的長(zhǎng)度
.forEach(collection, function) , .each()和.forEach() 已經(jīng)是一樣了, 注意.each(里面不能用yield表達(dá)式)
.flatMap(collection, [iteratee=.identity]),將數(shù)組里的每個(gè)元素都經(jīng)過(guò)后面的function計(jì)算一遍,輸出一個(gè)計(jì)算過(guò)的數(shù)組

function duplicate(n) {
  return [n, n];
}
 
_.flatMap([1, 2], duplicate);
// => [1, 1, 2, 2]

.groupBy(collection, [iteratee=.identity]), 返回的是key-values 對(duì),就是一個(gè)個(gè)object。這個(gè)跟java8 lambda的xx.stream().collect(Collectors.groupingBy(o -> o.id)); 很像。
但是這里想說(shuō)的是,當(dāng)在js里要用_.each()按object來(lái)遍歷這個(gè)結(jié)果,是這樣寫的:

_.each(itemLinesGroupByLocation, (values, keys)=>{
......
})
不是(key, values)哦

當(dāng)然還可以用其他方式遍歷:

for(let key in itemLinesGroupByLocation){
    console.log(key)
    console.log(itemLinesGroupByLocation[key])
}
或者
for(let locationId of _.keys(itemLinesGroupByLocation)){
    let items = itemLinesGroupByLocation[locationId]
    ...
}

--array操作--

_.head([1, 2, 3]); _.head() = _.first() 取出數(shù)組的第一個(gè)元素。
_.uniq(array), 去重?cái)?shù)組或者collection
_.union([arrays]),聯(lián)合兩個(gè)數(shù)組,會(huì)去重
_.includes(collection, value, [fromIndex=0]), 查看某個(gè)值是否在這個(gè)collection里
_.flatten(array) 一維扁平化數(shù)組

_.flatten([1, [2, [3, [4]], 5]]);
// => [1, 2, [3, [4]], 5]

_.remove(array, function) 從數(shù)組中刪掉符合條件的元素
舉例

var array = [1, 2, 3, 4];
var evens = _.remove(array, function(n) {
  return n % 2 == 0;
});
 
console.log(array);
// => [1, 3]
 
console.log(evens);
// => [2, 4]

--Math操作--

_.ceil(4.006); = 5 取大
_.sum(array) 把數(shù)組的所有值加起來(lái)輸出一個(gè)結(jié)果
.sumBy(array, [iteratee=.identity]),遍歷數(shù)組,找出function里指定的元素,并求和

var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
 
_.sumBy(objects, function(o) { return o.n; });
// => 20
 
// The `_.property` iteratee shorthand.
_.sumBy(objects, 'n');
// => 20

--array操作--

_.pick(object, [paths]), 從一個(gè)object里挑出幾個(gè)屬性

var object = { 'a': 1, 'b': '2', 'c': 3 };
 
_.pick(object, ['a', 'c']);
// => { 'a': 1, 'c': 3 }

.pickBy(object, [predicate=.identity]), 第二部分是個(gè)函數(shù),作用于每個(gè)元素

var object = { 'a': 1, 'b': '2', 'c': 3 };
 
_.pickBy(object, _.isNumber);
// => { 'a': 1, 'c': 3 }

--Object操作--

_.keys(Object) , 官網(wǎng)說(shuō)它的作用是:

Creates an array of the own enumerable property names of `object`.

**Note:** Non-object values are coerced to objects. See the [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) for more details.

實(shí)際使用中,我大多數(shù)用于取_.groupBy()后的map的keys, 不過(guò)今天注意到官網(wǎng)在對(duì)這個(gè)function解釋的例子中有個(gè)

_.keys('hi');
// => ['0', '1']

網(wǎng)上一搜,為什么參數(shù)為一個(gè)字符串的時(shí)候輸出0,1.甚至我把hi改成hiii,輸出的是0,1,2,3,看起來(lái)是字符串的index。網(wǎng)上也沒(méi)找到合理的解釋。于是注意到官網(wǎng)有這么一句Note: Non-object values are coerced to objects. See the ES spec for more details. 也就是說(shuō)‘hi’ 此時(shí)被轉(zhuǎn)成object,但是為什么是0,1,于是做了個(gè)實(shí)驗(yàn),字符串實(shí)例化成StringObject后確實(shí)用index做為key了,勉強(qiáng)可以解釋得通了。官網(wǎng)的解釋是在看不太懂。。讀的懂的請(qǐng)留言,互相學(xué)習(xí):http://ecma-international.org/ecma-262/6.0/#sec-object.keys

image.png

.merge(object, [sources]), 官網(wǎng)對(duì)它的描述是跟.assign很像,那么就先看下_.assign是干嘛的,理解這個(gè)方法我是參閱了https://scarletsky.github.io/2016/04/02/assign-vs-extend-vs-merge-in-lodash/,作者對(duì)官網(wǎng)描述的翻譯讓我豁然開(kāi)朗。。淚流滿面,原來(lái)是這樣,
_.assign() , 把源對(duì)象(sources)的屬性分配到目標(biāo)對(duì)象(object),源對(duì)象會(huì)從左往右地調(diào)用,后面對(duì)象的屬性會(huì)覆蓋前面的。

看完摘錄自這位作者的例子后就懂了。

_.assign({}, { a: 1 }, { b: 2 });  // 意思就是,{}+{a:1}={a:1}+{b:2}={a:1, b:2}
// { a: 1, b: 2 }

_.assign({}, { a: 1 }, { b: 2 }, { a: 2 });   // 后面的 { a: 2 } 把前面的 { a: 1 } 覆蓋了
// { a: 2, b: 2 } 
merge 也和 assign 類似,不同的地方在于 merge 遇到相同屬性的時(shí)候,如果屬性值為純對(duì)象(plain object)或者集合(collection)時(shí),不是用后面的屬性值去覆蓋前面的屬性值,而是會(huì)把前后兩個(gè)屬性值合并。
如果源對(duì)象的屬性值為 undefined,則會(huì)忽略該屬性。
assign(
  {},
  { a: 1 },
  { b: { c: 2, d: 3} },
  { b: { e: 4 } }
)
// { a: 1, b: { e: 4 } }
merge(
  {},
  { a: 1 },
  { b: { c: 2, d: 3} },
  { b: { e: 4 } }
)
// { a: 1, b: { c: 2, d: 3, e: 4 } }

我今天替別人填了個(gè)坑就是.union() 他寫成了.merge().
總結(jié)就是,如果只是要合并兩個(gè)純粹的list(指元素是基礎(chǔ)類型)并去重,用.union([arrays])。如果要合并object組成的list,并去重, 就用.merge(object, [sources])。例子:

let studentClass1 = [{"name":"lucy", "age":10}];
let studentClass2 = [{"name":"lucy", "age":10}, {"name":"sam", "age":11}];
let allStudents = _.union(studentClass1, studentClass2);  // 不會(huì)合并,會(huì)去重
let allStudents2 = _.merge(studentClass1, studentClass2); //會(huì)合并,會(huì)去重
console.log(allStudents);
console.log(allStudents2);
console.log(_.union(["1","2"],["2","3"])); //會(huì)合并,會(huì)去重
// 結(jié)果
[ { name: 'lucy', age: 10 },
  { name: 'lucy', age: 10 },
  { name: 'sam', age: 11 } ]
[ { name: 'lucy', age: 10 }, { name: 'sam', age: 11 } ]
[ '1', '2', '3' ]
寫在最后,只是一些解釋,可不看。

在整理這篇文章之前,我發(fā)現(xiàn)我居然分不清lodash的collection 和array, 平時(shí)在使用中也沒(méi)有遇到因?yàn)閏ollection和array使用出錯(cuò)的問(wèn)題。因此出于責(zé)任心,我找了相關(guān)的資料, #####總結(jié)就是好像二者區(qū)別不大,在用lodash的時(shí)候應(yīng)該是沒(méi)影響,所以上面的中文解釋,我也沒(méi)區(qū)分?jǐn)?shù)組或者集合了:
https://blog.csdn.net/Soaring_Tiger/article/details/48180511
引用這位作者的解釋:
在lodash中,Collection是一個(gè)抽象的概念,指的是那些我們準(zhǔn)備用來(lái)迭代的Javascript object,可以是 數(shù)組、字符串或者object對(duì)象,至于這些數(shù)據(jù)類型之間的差別細(xì)節(jié),則被lodash隱藏起來(lái)了,作為開(kāi)發(fā)者你不用操心。

而lodash的 Array方法則沒(méi)有那么抽象,它們要求你處理的就是實(shí)實(shí)在在的數(shù)組。從這個(gè)意義上講,即便Array方法沒(méi)有顯式的檢查你提交的數(shù)據(jù)類型,但是它們要求你提交的數(shù)據(jù)得有數(shù)值型length屬性(a numerical length property)。

實(shí)際上,在大部分時(shí)候,你并不需要嚴(yán)格得區(qū)分 arrays 和 collections 之間的差別,因?yàn)槟忝鎸?duì)的大多數(shù)collections都是以數(shù)組的形式出現(xiàn)的,只有在比較少的情況下,你會(huì)面臨著差別 。所以你只要記住,Array方法是嚴(yán)格要求數(shù)據(jù)類型(有數(shù)值型length屬性)的就行了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容