日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用技巧_Lodash 使用技巧

發布時間:2024/10/6 编程问答 71 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用技巧_Lodash 使用技巧 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


點擊 閱讀原文 可使用 語雀 查看,排版樣式更佳。
我第一次使用 Lodash 還是在實習的時候,當時并不喜歡用它,因為我覺得:上面很多東西在 ES6+ 已經實現了,還有就是很多函數看不懂怎么使用。
直到有一次,我在 npm 上看到, Lodash 的周下載量是 React 的四倍多,就覺得應該好好了解下這個庫了。

使用原因

比 ES6+ 更強大

比如 _.drop,它就相當于 Array.prototype.shift(),但 _.drop 可以增加參數,扔掉 n 個,而 shift 只能扔掉 1 個。再比如 _.set _.get 這在操作深層數據結構時非常有用,而 js 本身并未提供這種函數。

不會輕易報錯

以 _.includes 為例:
就是參數是 undefined,代碼也能正常執行下去,但你如果使用 Array.prototype.includes() 那就會變成 undefined.includes(),這不就報錯了嘛。

0 dependencies

沒有外部依賴,代碼全是由官方人員維護,有足夠的安全性、穩定性,如果你了解 node_modules 的痛點,就應該知道這是多么的重要。
理想情況下,沒人使用 ES6+ 的一些 prototype 上的操作,而是全部使用 Lodash 來實現,那就能干掉 polyfill 了,減少代碼打包的體積(但有可能你引用的三方包需要 polyfill,你的努力就全白費了 ?)。

使用技巧

其實只要仔細看下官方文檔就可以使用了(沒有什么是看官方文檔解決不了的,如果有,那就再看一遍 ?)。當然,官方文檔也確實有些枯燥,下面介紹下我常使用的方法以及用途吧。
文檔把函數一共分了幾大類,最常用的莫過于 Array 和 Collection 了(Collection 就是 Array 或 Object)。

Array

_.chunk(array, [size=1])
這個就是把一個數組按照 size 去分成好幾個數組,我一直覺得這個沒啥用,直到我遇到了這種需求:
就是寫一個小面板,那里 3 個一列,順序放置,這不就是 chunk 嘛,真香!

_.compact(array)
把 array 中的 falsey 值去掉,可用于給后端傳參時_.difference(array, [values])
去掉 array 中和 values 相同的值。返回新數組,不會更改 array

_.differenceBy(array, [values], [iteratee=_.identity])
這里的 _.xxxBy 對后面有指導性意義。重點看 iteratee 參數,它有個默認值是 _.identity(它是一個函數,它返回接收到的第一個參數),iteratee 應該是一個函數,它只帶一個參數 value(array 和 values 的值),iteratee 的作用就是你可以接收 value 返回 nextValue,nextValue 用于 _.difference,就是相當于你有的進一步去改造 array 和 values 的能力,但比較還是由 _.differenceBy 來完成。當 iteratee 字符串或其他一些特殊類型的字面量時,可以代表某些函數簡寫的參數,如下:
這里 iteratee 是字符串 'x',其實就相當于如下代碼:

_.differenceBy([{?x:?2?},?{?x:?1?}],?[{?x:?1?}],?_.property('x'));

有挺多函數都可以使用這種簡寫操作,具體的可以參考下文檔。

_.differenceWith(array, [values], [comparator])
這里的 _.xxxWith 對后面有指導性意義。這里 comparator 函數就更強大了,比較的工作也由你來完成,你只需要在 comparator 函數中返回布爾值就好了,comparator 的參數是 (arrVal, othVal)

_.drop(array, [n=1])
在 array 中扔掉前 n 個元素,返回其余后面的元素,.dropRight 是倒著扔。.dropWhile(array, [predicate=.identity]) 是一直扔,直到 predicate 返回 false 為止,.dropRightWhile 同理

_.take(array, [n=1])在 array 只拿前 n 個元素,其余的不要,_.takeRight _.takeWhile _.takeRightWhile 同理

.findIndex(array, [predicate=.identity], [fromIndex=0])
遍歷 array,找到第一個 predicate 函數返回 true 的值的下標并返回,_.findLastIndex 是倒著找,這個和 Collection 中的 _.find 非常像,只不過 _.find 返回的是找到值,而不是下標(并且 Object 也沒下標呀),_.findLast 同理_.head(array)
返回 array 中第一個元素_.last(array)
返回 array 中最后一個元素_.tail(array)
返回一個數組,除了 array 中第一個元素_.initial(array)
返回一個數組,除了 array 中最后一個元素

_.flatten(array)
拍平 array 中的數組的第一層,可用于兼容參數,比如 foo(a) 參數 a 可以是一個字符串或字符串數組,那 foo 函數里,就可以調用 _.flatten([a]) 就能統一拿到 a 數組。_.flattenDeep 是所有層都拍平,_.flattenDepth 可以指定層。_.intersection([arrays])
返回 arrays(代表多個數組)中的交集,_.intersectionBy 與 _.intersectionWith 同理

_.intersection([2,?4,?6,?1,?2,?3],?[1,?2,?9],?[1,?2,?6]);
//?[2,?1]

_.union([arrays])
返回 arrays(代表多個數組)中的并集, _.unionBy 與 _.unionWith 同理

_.union([2,?4,?6,?1,?2,?3],?[1,?2,?9],?[1,?2,?6]);
//?[2,?4,?6,?1,?3,?9]

_.nth(array, [n=0])
返回 array 中的第 n 項,有趣的是,n 可以是負數,代表倒數,與 Array.prototype.slice() 類似

_.pullAll(array, values)
拿掉 array 中和 values 相同的值。和上面的 _.difference 作用一樣,只不過會直接改變 array 原數組,_.pullAllBy 和 _.pullAllWith 同理_.pullAt(array, [indexes])
拿掉 array 中 indexes 下標的值,會改變 array 原數組

_.remove(array, [predicate=_.identity])
通過 predicate 函數,移走 array 中返回 false 的元素,會改變 array 原數組_.uniq(array)
給 array 去重,_.uniqBy 與 _.uniqWith 同理,數組去重還是很常用噠(下次面試官說:數組去個重,你就可以寫 _.uniq([1, 1, 2]) 試試,不知道面試官會不會打你 ?)

Collection

不知你有沒有想過,為什么 Collection 是 Array 或 Object 呢?還有為什么 JS 的數組不會越界呢?
其實 JS 中的數組并不是真正意義上的數組,如我搜的 C++ 數組定義如下:

C++ 支持數組數據結構,它可以存儲一個固定大小的相同類型元素的順序集合。所有的數組都是由連續的內存位置組成。最低的地址對應第一個元素,最高的地址對應最后一個元素。

這時你應該想起來了,JS 中的函數、數組、正則表達式的原型鏈上都有 Object:(每一個對象都有 __proto__ 屬性,當調用這個對象的變量或方法時,如果沒有找到,會沿著 __proto__ 屬性一直向上找)
所以 JS 數組只是一種自帶一些特殊操作(如 push、shift)的 Object,所以類數組就是一個帶有 length 屬性的對象,用 Array.from() 就能輕松的把它轉換為數組。
這也是為什么 JS 用數組實現一個 ?;蜿犃?都非常簡單(當然,我這里說的只是簡單的模擬行為),而 C++ 這種,就還需要特殊的數據結構(queue、stack)來支持。我也認為,這正是 JS 的精妙之處,因為適用場景就是如此。
回到正題,接下來是 Collection 的常用方法。

_.countBy(collection, [iteratee=_.identity])
通過 iteratee 函數的返回值去給 collection 分類計數,返回值為 key 計數值為 value_.groupBy(collection, [iteratee=_.identity])
通過 iteratee 函數的返回值去給 collection 分類,返回值為 key 被分類的項為 value

_.forEach(collection, [iteratee=_.identity])
遍歷 collection,iteratee 可以返回 false,循環就會 break。這一個方法就完成了 Array.prototype.forEach() 和 Object.entries(),賊強(注意:collection 如果是 Object 且有 length 屬性,就會被當做數組來處理,想要被正確處理的話,可以使用 _.forIn 或 .forOwn,還是建議正常 Object 就不要用 length 屬性了吧).forEachRight 同理_.every _.some _.includes _.find _.findLast _.filter _.map _.reduce _.reduceRight
以上都是 JS 原生存在的方法了,那為什么不用原生的而要用這里的呢?
瀏覽器兼容性更好;這些既能用到 Array 上又能用到 Object 上,有時還能用到 String 上;實現更強的功能,代碼更少,如下舉例:

var?users?=?[{?user:?'barney'?},?{?user:?'fred'?}];

//?Lodash?解法
//?The?`_.property`?iteratee?shorthand.
_.map(users,?'user');
//?=>?['barney',?'fred']

//?原生解法
users.map(i?=>?i.user);
//?=>?['barney',?'fred']

_.sortBy(collection, [iteratees=[_.identity]])
給 collection 排序,這是個比較正常的排序,默認升序,并不像 Array.prototype.sort() 都要轉成字符串再排序,而且很容易就能支持相等時的二級排序。

var?array1?=?[1,?30,?4,?21,?100000];
array1.sort();
//?=>?[1,?100000,?21,?30,?4]
_.sortBy(array1);
//?=>?[1,?4,?21,?30,?100000]?

var?users?=?[
??{?user:?'fred',?age:?48?},
??{?user:?'barney',?age:?36?},
??{?user:?'fred',?age:?40?},
??{?user:?'barney',?age:?34?},
];
//?當?user?相等時,使用?age?排序
_.sortBy(users,?['user',?'age']);
//?=>?objects?for?[['barney',?34],?['barney',?36],?['fred',?40],?['fred',?48]]

_.orderBy(collection, [iteratees=[_.identity]], [orders])
這個和 _.sortBy 一樣的,就是可以自定義升序或降序

_.partition(collection, [predicate=_.identity])
把 collection 分為兩份,分別是 predicate 返回真的和假的

_.reject(collection, [predicate=_.identity])
和 _.filter 相反,返回 predicate 為假的值

_.sample(collection)
返回 collection 中任意一個值,_.sampleSize 返回 collection 中任意 n 個值,不會重復

_.shuffle(collection)
返回打亂順序后的 collection_.size(collection)
返回 collection 的項目個數,感覺比 length 好用多了

其他類型

有些其他類型的,也比較常用,在此說下:_.now()
返回時間戳_.debounce(func, [wait=0], [options={}])
返回 func 經過防抖后的函數_.throttle(func, [wait=0], [options={}])
返回 func 經過節流后的函數
這兩個函數常用于輸入框搜索中,如在 React Hooks 下,可以這樣使用:

//?React?Hooks?組件中
const?handleRequest?=?useRef(
??debounce(url?=>?{
????request(url);
??},?600),
);

_.unary(func)
讓 func 只會使用第一個參數

_.cloneDeep(value)
深克隆 value_.isEqual(value, other)
深比較 value 和 other 是否相等。這塊讓我想到一個有趣的問題,記得有人說深比較是否相等可以用 JSON.stringify() 其實這個不對,如下所示就能證明:
注意:這兩個要慎用啊,因為都會一直遞歸到最深層,建議只有當你知道這個對象很簡單,并且以后也不會變復雜的情況下,再使用他們。

_.get(object, path, [defaultValue])
獲取 object 的 path 上的值,如果沒有,就用 defaultValue,這個我經常使用,當不確定這個值是否存在時,還能給個 defaultValue 來繼續下面的操作_.set(object, path, value)
給 object 的 path 賦值 value,如果 path 的值不存在,則會一直創建_.unset(object, path)
相等于 delete 掉 path 上的值

_.omit(object, [paths])
忽略掉 object 的 paths 上的值_.pick(object, [paths])
只取 object 的 paths 上的值_.matches(source)
返回一個函數,如果部分匹配正確,那這個函數將返回 true_.range([start=0], end, [step=1])
生成一個范圍內的數字數組

結語

本文只介紹了一些簡單、常用的函數,希望能以通俗易懂的方式表達出來。提前把這些方法的作用看一下還是有必要的,當遇到合適場景的時候,就直接使用,而不是自己造(造出的又全是 bug?)。
歡迎關注我的公眾號,或使用語雀 https://www.yuque.com/zcue/blog 查看:

總結

以上是生活随笔為你收集整理的使用技巧_Lodash 使用技巧的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。