1. 程式人生 > >Lodash中十個常用的工具函式

Lodash中十個常用的工具函式

當你使用JavaScript進行程式設計的時候,你很可能需要經常重複寫一些工具函式,尤其是處理字串和物件。 即使ES6已經被標準化了,JavaScript開發者依然無法獲得像Objective-C或Ruby那樣多的語法糖。 因此,在JavaScript應用中仍然被重複的編寫大量的工具函式。而本文將會為你帶來的救星就是 Loadsh 。

本文將要介紹的是Loadash中的10個常用的工具函式,當然對於不同的工作,你很可能也會需要其他的工具函式, 本文僅作為一個入門Lodash的引子,完整的函式列表請參考Lodash的 API文件 。 本文使用的Lodash版本是 3.10.1 。

Statement

原文地址: http://colintoh.com/blog/lodash-10-javascript-utility-functions-stop-rewriting

迴圈N次

// 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(){
	// ...
});

for 迴圈是一個常見的使用場景,但是它會引入附加變數汙染作用域(scope)。 你可以組合使用陣列和 apply

 方法來避免直接使用for迴圈,這樣也避免了作用域汙染的問題。 但是,這種寫法不夠直觀。Lodash總的 _.times 方法就非常的直觀易用。

迭代陣列並返回每一項中深度巢狀的屬性

// 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');

Lodash中的 map 方法和JavaScript中原生的陣列方法非常的像,但它還是有非常有用的升級。 你可以通過一個字串而不是回撥函式來導航到深度巢狀的物件屬性。

建立一個大小為N的陣列,並且為他們新增相同的字首

// Create an array of length 6 and populate them with unique values. The value must be prefix with "ball_".
// eg. [ball_0, ball_1, ball_2, ball_3, ball_4, ball_5]

// Array's map method.
Array.apply(null, Array(6)).map(function(item, index){
	return "ball_" + index;
});


// Lodash
_.times(6, _.uniqueId.bind(null, 'ball_'));

從前面的例子中我們已經知道了 _.times 的作用。如果你將它和 _.uniqueId 方法組合使用, 我們可以獲得一個更簡潔的解決方案。如果你不想重複的宣告上下文,Lodash也提供了一個可選方案。

避免使用 .bind(null,...)

// Lodash
_.times(6, _.partial(_.uniqueId, 'ball_'));

_.partial 方法完成的工作和原生的 bind() 方法很類似,除了它假設當前的上下文為 this。 因此,沒必要再額外的指定上下文引數。

深度克隆JavaScript物件

var objA = {
	"name": "colin"
}

// Normal method? Too long. See Stackoverflow for solution: http://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript

// Lodash
var objB = _.cloneDeep(objA);
objB === objA // false

深度克隆JavaScript物件是困難的,並且也沒有什麼簡單的解決方案。你可以使用原生的解決方案: JSON.parse(JSON.stringify(objectToClone)) 進行深度克隆。但是,這種方案僅在物件內部沒有方法的時候才可行。

Lodash提供了 _.cloneDeep 方法來幫你簡單的完成物件的深度克隆操作。當然,使用 _.clone你還能靈活的指定克隆的深度。

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

// 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

擴充套件物件

// Adding extend function to Object.prototype
Object.prototype.extend = function(obj) {
	for (var i in obj) {
		if (obj.hasOwnProperty(i)) {
			this[i] = obj[i];
		}
	}
};

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

objA.extend(objB);
objA; // {"name": "james", "age": 17, "car": "suzuki"};

// Lodash
_.assign(objA, objB);

_.assign 方法也可以接收多個引數物件進行擴充套件。

var objA = {"name": "colin", "car": "suzuki"};
var objB = {"name": "james", "age": 17};
var objC = {"pet": "dog"};

// Lodash
_.assign(objA, objB, objC)
// {"name": "james", "car": "suzuki", "age": 17, "pet": "dog"}

去掉物件的某些屬性

// 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"}

原生的途徑你只能傳遞陣列作為引數。有時我們可能也想對字串引數進行單個key的刪除,甚至是傳入一個比較器。

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

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

你需要注意的是, _.omit 方法會返回一個新的物件,而不會修改原來的物件。

從某個物件中選擇部分屬性組成新的物件

// 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}

_.pick 方法與 _.omit 方法正好相反,它會從物件中選擇指定的屬性組裝成新的物件。 和 _.omit 一樣, _.pick 也會返回新的物件,並且能夠傳入字串、陣列、比較器函式。

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

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']

JSON.parse的錯誤處理

// Using try-catch to handle the JSON.parse error
function parse(str){
	try {
		return JSON.parse(str);
	}

	catch {
		return false;
	}
}

// With Lodash
function parseLodash(str){
	return _.attempt(JSON.parse.bind(null, str));
}

parse('a'); // false
parseLodash('a'); // Return an error object

parse('{"name": "colin"}'); // Return {"name": "colin"}
parseLodash('{"name": "colin"}'); // Return {"name": "colin"}

當你使用 JSON.parse 時,請記住一定要進行錯誤處理。如果沒有即使得進行處理, 很可能成為巨大的安全隱患。永遠都不要假設你接收到的一定是正確有效的JSON物件。 取代原生的使用try...catch 進行錯誤處理,你可以使用 _.attempt 方法。 如果出錯的話,它會返回一個Error 物件。

小結

Lodash能夠為你解決非常多小的細節問題,推薦你在JavaScript專案中使用它,它能讓你的程式碼看起來更加的精簡, 也更加的健壯,幫你避免很多重複的應用邏輯。此外,Lodash也迫使我們以函式式的方式來思考程式設計。 我們可以將應用切分為若干個小且專注的模組。這種模組化能夠提高我們應用程式在測試時的程式碼覆蓋率。