Lodash 這一篇實在讓我不知道要放在哪啊!是一個使用範圍非常廣的函式庫,既然已經到了接近尾聲的最後幾天了,就來看看這個相當長壽的函式庫吧!
很多我們平常習以為慣的原生 function,在 ES6+ 還未推出之前,其實都還得用比較麻煩的寫法。
比如 ES7 釋出的 Array.prototype.includes()
用來判斷陣列是否包含特定的元素:
const array = [1, 2, 3];
console.log(array.includes(2)); // true
但如果在 ES7 以前的時代,想要使用這種語法,就得用到一些 polyfill 的寫法,像是這樣:
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
if (sameValueZero(o[k], searchElement)) {
return true;
}
// c. Increase k by 1.
k++;
}
// 8. Return false
return false;
}
});
}
相似的 case 還滿多的,畢竟 ECMAScript 不斷推陳出新,就代表著一直有許多語法可以被優化,或者有更方便的函式釋出。但這種工具類的函式需求,從以前就在了,總不可能每個專案都要寫一大堆這種 polyfill 吧?
Lodash 早在 2012 年就出現了,當時主打的是現代化 JavaScript 的工具類 library:
A modern JavaScript utility library delivering modularity, performance & extras.
主要處理的就是針對 array, number, object, string 等基本型態的迭代、操作,視為對 JavaScript 底層的功能擴充,甚至也支援 FP(Functional Programming) 的一些常用語法。
比如上面提到的 includes
,使用 lodash 的話:
var array = [1, 2, 3];
console.log(_.includes(array, 2)); // true
比起 polyfill,程式碼整個簡潔許多,而我們也不需要去維護那一大堆函式庫,只要引入 Lodash,就可以直接使用許多方便的函式了。
雖然前面舉例的 includes
在現代瀏覽器都已經有支援了,所以這時候直接用原生的 Array.prototype.includes()
就好了,如果用 _.includes
反而有點多此一舉,還得多引入一個套件。
但有些工具函式可能比較複雜,連 ECMAScript 都還沒支援,這時候 lodash 的存在就很有價值。
比如有些時候需要針對資料「深度拷貝」時,就可以用到 _.cloneDeep
:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]); // false
或者需要判斷是否為空的時候,可以用到 _.isEmpty
:
console.log(_.isEmpty(undefined)); // true
console.log(_.isEmpty(null)); // true
console.log(_.isEmpty('')); // true
console.log(_.isEmpty({})); // true
console.log(_.isEmpty([])); // true
console.log(_.isEmpty({a: '1'})); // false
有部分函式隨著 ECMAScript 更新,已經可以使用原生 function 來處理,可以參考 You-Dont-Need-Lodash-Underscore
Lodash 算是滿泛用的工具函式庫,我幾乎是在每個專案都用到XD
不過因為目前許多比較基本的 utils 都已經由 ECMAScript 實作了,使用 Lodash 的時機應該更著重在比較進階的邏輯計算,或者像是 FP 的需求,如果專案本身並不複雜,Lodash 用得不多,其實不用特地引用 Lodash 來占空間。
研究 Lodash 的過程中,仔細去比對了一部份 You-Dont-Need-Lodash-Underscore 提到的函式,因為很多函式其實日常都用得很順手了,沒想過原來這些東西有一些歷史演進的脈絡,趁這個機會理解了一下每個函式的背景,以及它們的 polyfill 可以多麼複雜XD
Lodash
You-Dont-Need-Lodash-Underscore