首页 > 代码库 > (一)underscore入门和数组类工具API学习

(一)underscore入门和数组类工具API学习

underscore.js是一个JS框架,在原生javascript基础上提供了很多有用的工具API。apache提供了commons-lang、commons-io、commons-collections等jar包提供很多java语言常用的工具方法,underscore.js功能与之类似。经常开发JS代码的都知道,JS原生的Array、String等内置的API很少,不能满足实际开发过程中国的需要。所以引入一些工具库很有必要,避免我们重复的写一些本来应该公用的方法。

1.学习资料

underscore官网  http://underscorejs.org/
官网中文翻译     http://www.css88.com/doc/underscore/
underscore比较简单,有官方的参考文档就够了。本文是用的underscore.js当前最新版本1.7.0。
对于简单的API,直接复制官方的说明例子,对于一些不太好理解的API会详细说明。

2.数组相关API
Note: All array functions will also work on the arguments object. However, Underscore functions are not designed to work on "sparse"(稀疏的) arrays.
这些数组API不仅适用于js中的数组类型,也适用于arguments对象。arguments是每个js函数内部都有的一个对象,存储了调用该函数时传递的所有参数值,它很类似于数组,但实际上不是数组。至于什么是稀疏数组,什么是密集数组,参考我的另一篇文章:稀疏数组和密集数组

first

first_.first(array, [n]) Alias: head, take 
Returns the first element of an array. Passing n will return the first n elements of the array.

_.first([5, 4, 3, 2, 1]);
=> 5
initial

initial_.initial(array, [n]) 
Returns everything but the last entry of the array. Especially useful on the arguments object. Pass n to exclude the last n elements from the result.

_.initial([5, 4, 3, 2, 1]);
=> [5, 4, 3, 2]
_.initial([5, 4, 3, 2, 1],2);
=> [5, 4, 3]
last

last_.last(array, [n]) 
Returns the last element of an array. Passing n will return the last n elements of the array.

_.last([5, 4, 3, 2, 1]);
=> 1
rest

rest_.rest(array, [index]) Alias: tail, drop 
Returns the rest of the elements in an array. Pass an index to return the values of the array from that index onward.

_.rest([5, 4, 3, 2, 1]);
=> [4, 3, 2, 1]
_.rest([5, 4, 3, 2, 1],3);
=> [2, 1]
compact(删除false值)

compact_.compact(array) 
Returns a copy of the array with all falsy values removed. In JavaScript, falsenull0,""undefined and NaN are all falsy.

_.compact([0, 1, false, 2, ‘‘, 3]);
=> [1, 2, 3]
_.compact([0, 1, 2, 3, 2, 1, 3]);
=> [0, 1, 2, 3, 2, 1, 3]

flatten(数组降维)

flatten_.flatten(array, [shallow]) 
Flattens a nested array (the nesting can be to any depth). If you pass shallow=true, the array will only be flattened a single level.

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

_.flatten([1, [2], [3, [[4]]]], true);
=> [1, 2, 3, [[4]]];
without(数组减法)

without_.without(array, *values) 
Returns a copy of the array with all instances of the values removed.

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
=> [2, 3, 4]
union(求并集)

union_.union(*arrays) 
Computes the union of the passed-in arrays: the list of unique items, in order, that are present in one or more of the arrays.

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]
intersection(求交集)

intersection_.intersection(*arrays) 
Computes the list of values that are the intersection of all the arrays. Each value in the result is present in each of the arrays.

_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]
difference(数组减法)

difference_.difference(array, *others) 
Similar to without, but returns the values from array that are not present in the otherarrays.

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]
uniq

uniq_.uniq(array, [isSorted], [iteratee]) Alias: unique 
Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iteratee function.

_.uniq([1, 2, 1, 3, 1, 4]);
=> [1, 2, 3, 4]
_.uniq([40, "", 11, false, 1, 0]);
=> [40, "", 11, false, 1, 0]
iteratee的函数声明形式:
// value:数组中元素的值
// index:所在的索引
// inputArray:元素的数组 
// _.uniq([40, "", 11, false, 1, 0],false,iterateeFunction);
// inputArray就代表[40, "", 11, false, 1, 0]这个数组
// 数组中每个元素都会调用iterateeFunction,uique去重的时候,用该函数转换后的值做比较
function iterateeFunction(value,index,inputArray)
{

}

关于iteratee,可以看到默认情况下,unique()函数使用===作为相等的条件。在===模式下,false不等于0;如果在==模式下,false等于0。
_.uniq([40, "", 11, false, 1, 0],false,function(value,index,origialArray){
 
	if(value)
	{
		return value;//如果元素强制转换成boolean是true,返回元素本身
	}
	else
	{
		// 所有false类型的值,都统一视为0
	    return 0;
	}
 });
返回值是[40,0,11,1]。关于js中的boolean类型转换,参考我的另一篇文章

zip

zip_.zip(*arrays) 
Merges together the values of each of the arrays with the values at the corresponding position. Useful when you have separate data sources that are coordinated through matching array indexes. If you‘re working with a matrix of nested arrays, _.zip.applycan transpose the matrix in a similar fashion.

_.zip([‘moe‘, ‘larry‘, ‘curly‘], [30, 40, 50], [true, false, false]);
=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]

 // 数组维度不同,会以长度最长的为准,没有元素会用undefined填充
 // zipArray是一个4 * 3的二维数组
 var zipArray = _.zip(['moe', 'larry', 'curly'], [30, 40, 50,1000], [true, false, false]);
返回的zipArray数组是:[["moe", 30, true],  ["larry", 40, false],  ["curly", 50, false],  [undefined,1000,undefined]]

 // a matrix of nested arrays
 var nestedZip = [['moe', 'larry'], [30, 40], [true, false]];
 var zipArray = _.zip.apply(_, nestedZip);
返回的zipArray数组是:[["moe", 30, true],  ["larry", 40, false]]

object

object_.object(list, [values]) 
Converts arrays into objects. Pass either a single list of [key, value] pairs, or a list of keys, and a list of values. If duplicate keys exist, the last value wins.

_.object([‘moe‘, ‘larry‘, ‘curly‘], [30, 40, 50]);
=> {moe: 30, larry: 40, curly: 50}

_.object([[‘moe‘, 30], [‘larry‘, 40], [‘curly‘, 50]]);
=> {moe: 30, larry: 40, curly: 50}
indexOf

indexOf_.indexOf(array, value, [isSorted]) 
Returns the index at which value can be found in the array, or -1 if value is not present in the array. If you‘re working with a large array, and you know that the array is already sorted, pass true for isSorted to use a faster binary search ... or, pass a number as the third argument in order to look for the first matching value in the array after the given index.

_.indexOf([1, 2, 3], 2);
=> 1
lastIndexOf

lastIndexOf_.lastIndexOf(array, value, [fromIndex]) 
Returns the index of the last occurrence of value in the array, or -1 if value is not present. Pass fromIndex to start your search at a given index.

_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
=> 4
sortedIndex

sortedIndex_.sortedIndex(list, value, [iteratee], [context]) 
Uses a binary search to determine the index at which the value should be inserted into the list in order to maintain the list‘s sorted order. If an iteratee function is provided, it will be used to compute the sort ranking of each value, including the value you pass. The iteratee may also be the string name of the property to sort by (eg. length).

_.sortedIndex([10, 20, 30, 40, 50], 35);
=> 3

var stooges = [{name: ‘moe‘, age: 40}, {name: ‘curly‘, age: 60}];
_.sortedIndex(stooges, {name: ‘larry‘, age: 50}, ‘age‘);
=> 1
注意:由于需要使用二分搜索,所以要求数组一定要是有序的,而且还要钱数组一定要是升序的。
 // 二分搜索,而且数组只能是升序
 console.log("asc=" + _.sortedIndex([10, 20, 30, 40, 50], 35));//3(正确的)
 console.log("desc=" + _.sortedIndex([50, 40, 30, 20, 10], 35));//5(这是错误的)

为什么了会这样呢,关键是二分搜索时候的比较条件,看下underscore.js源码
  // Use a comparator function to figure out the smallest index at which
  // an object should be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iteratee, context) {
    iteratee = _.iteratee(iteratee, context, 1);
    var value = http://www.mamicode.com/iteratee(obj);>while循环中的条件判断,很显然要求数组必须是升序的!

iteratee函数声明形式如下:

function iteratee(item)
{
	
}
sortedIndex()执行的时候,会将list中的每一个值和value,都传入到iteratee中。

range

range_.range([start], stop, [step]) 
A function to create flexibly-numbered lists of integers, handy for each and map loops.start, if omitted, defaults to 0step defaults to 1. Returns a list of integers from start tostop, incremented (or decremented) by step, exclusive. Note that ranges that stopbefore they start are considered to be zero-length instead of negative — if you‘d like a negative range, use a negative step.

_.range(10);
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11);
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5);
=> [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1);
=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0);
=> []


(一)underscore入门和数组类工具API学习