Lodash,npm包倉庫中依賴最多的庫

簡介

lodash,是具有一致接口、模塊化、高性能等特性的 JavaScript 工具庫。提供瞭大量的工具函數,也正是因為這個原因,使得lodash成為瞭npm包庫中被其它庫依賴最多的庫。
就像jQuery在全部函數前加全局的$一樣,lodash使用全局的_來提供對工具的快速訪問。

var _ = require('lodash');

提高開發者效率

//copy一個JS對象

//原生方法
var a = {a:1,b:2,c:3};
var b = {};
for(var key in a) {
  b[key] = a[key];
}


//lodash方法
var b = _.clone(a);

隻用一個方法、一行代碼就可實現對JS對象的復制。
但在這裡,lodash的高效率特性並沒有體現出來

var a = {};
//創建一個元素數目較多的對象,否則復制時間太小,統計不精確
for(var i=0;i<1000000;i++) {
  a[i.toString()] = Math.floor(Math.random()*100000);
}

var b = {};
//console.time(label);
//console.timeEnd(label);
//兩者一一對應,用於統計兩者之間的代碼運行時間
console.time('native copy');
for(var key in a) {
  b[key] = a[key];
}
console.timeEnd('native copy');


var c = {};
console.time('lodash clone');
c = _.clone(a);
console.timeEnd('lodash clone');

運行結果:

native copy: 473ms
lodash clone: 581ms

提高程序運行效率

但在大多數情況下,lodash提供的工具函數是可以顯著提高程序運行效率的。

var array = [];
//生成一個100w 長度的數組,並賦值隨機數
for(var i=0;i<1000000;i++) {
  array.push(Math.floor(Math.random()*10000))
}


//原生forEach 遍歷
console.time('native for Each');
array.forEach(function (key) {

});
console.timeEnd('native for Each');

//lodash forEach 遍歷
console.time('lodash for Each');
_.forEach(array,function (key) {

});
console.timeEnd('lodash for Each');

運行結果:

native for Each: 32ms
lodash for Each: 11ms

可看到運行速度降低瞭近三倍。不知是否電腦環境、軟件版本不同的原因,在別人的電腦上的運行結果出現過

native for Each: 98ms
lodash for Each: 4ms

速度相差近瞭25倍。

惰性計算

lodash可以顯著提高計算效率的原因在於其對惰性計算的應用。

惰性求值,是一個計算機編程中的一個概念,它的目的是要最小化計算機要做的工作。

又稱延遲計算,特別用於函數式編程語言。表達式不在它被綁定到變量之後就立即求值,而是在該值被取用的時候求值,也就是說,語句如x:=expression; (把一個表達式的結果賦值給一個變量)明顯的調用這個表達式被計算並把結果放置到x中,但是先不管實際在x中的是什麼,直到通過後面的表達式中到x的引用而有瞭對它的值的需求的時候,而後面表達式自身的求值也可以被延遲,最終為瞭生成讓外界看到的某個符號而計算這個快速增長的依賴樹。

下面看一個簡單的延遲計算例子,一個簡單取餘的函數。

function mod (a,b){
    if(b==1) return 0;
    else return a % b ;
}

mod((1+3)*2,1)  // 0

可以看到由於 b 是 1,所以我們並不會用到 a 的值,但是依然計算瞭表達式(1+3)*2,這裡的計算就是浪費的。惰性求值則能避免這一情況。

看下面這份代碼:

var arr = _.range(100);

var a = _.chain(arr)
    .map(function (x) {
        console.log(1);
        return x+1;
    })
    .take(10)
    .value();

結果會輸出100個1。

為什麼會這樣?不是說在lodash中采用瞭惰性求值嗎?不應該輸出10個1嗎?

原來,在lodash中隻有數組超過200個才會啟動惰性求值。

var arr = _.range(200);

var a = _.chain(arr)
    .map(function (x) {
        console.log(1);
        return x+1;
    })
    .take(10)
    .value();

這樣,輸出就會是10個1瞭。

lodash常用工具函數

循環

// 1. Basic for loop.
for(var i = 0; i < 5; i++) {
    // ....
}

// 2. Using Array's join and split methods
Array.apply(null, Array(5)).forEach(function(){
    // ...
});

// Lodash
_.times(5, function(){
    // ...
});

迭代數組並返回每一項中深度嵌套的屬性

// Fetch the name of the first pet from each owner
var ownerArr = [{
    "owner": "Colin",
    "pets": [{"name":"dog1"}, {"name": "dog2"}]
}, {
    "owner": "John",
    "pets": [{"name":"dog3"}, {"name": "dog4"}]
}];

// Array's map method.
ownerArr.map(function(owner){
    return owner.pets[0].name;
});

// Lodash
_.map(ownerArr, 'pets[0].name');

在指定范圍內獲取一個隨機值

// Get a random number between 15 and 20.

// Naive utility method
function getRandomNumber(min, max){
    return Math.floor(Math.random() * (max - min)) + min;
}

getRandomNumber(15, 20);

// Lodash
_.random(15, 20);

Lodash中的random方法要比上面的原生方法更強大與靈活。你可以隻傳入一個參數作為最大值, 你也可以指定返回的結果為浮點數。

_.random(20); // Return random number between 0 to 20
_.random(15, 20, true); // Return random floating numbers between 15 and 20

從列表中隨機的選擇列表項

var luckyDraw = ["Colin", "John", "James", "Lily", "Mary"];

function pickRandomPerson(luckyDraw){
    var index = Math.floor(Math.random() * (luckyDraw.length -1));
    return luckyDraw[index];
}

pickRandomPerson(luckyDraw); // John

// Lodash
_.sample(luckyDraw); // Colin

也可指定返回元素的個數

var luckyDraw = ["Colin", "John", "James", "Lily", "Mary"];

// Lodash - Getting 2 random item
_.sample(luckyDraw, 2); // ['John','Lily']

從某個對象中選擇部分屬性組成新的對象

// Naive method: Returning a new object with selected properties 
Object.prototype.pick = function(arr) {
    var _this = this;
    var obj = {};
    arr.forEach(function(key){
        obj[key] = _this[key];
    });

    return obj;
};

var objA = {"name": "colin", "car": "suzuki", "age": 17};

var objB = objA.pick(['car', 'age']);
// {"car": "suzuki", "age": 17}

// Lodash
var objB = _.pick(objA, ['car', 'age']);
// {"car": "suzuki", "age": 17}

去掉對象的某些屬性

// Naive method: Remove an array of keys from object
Object.prototype.remove = function(arr) {
    var that = this;
    arr.forEach(function(key){
        delete(that[key]);
    });
};

var objA = {"name": "colin", "car": "suzuki", "age": 17};

objA.remove(['car', 'age']);
objA; // {"name": "colin"}

// Lodash
objA = _.omit(objA, ['car', 'age']); // {"name": "colin"}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *