underscore是一個很是實用的javascript庫,提供許多編程時須要的功能的支持,在不擴展任何javascript原生對象的狀況下提供不少實用的功能。主要涉及對Collection、Object、Array、Function的操做。一共60多個函數。javascript
函數介紹:html
1、Collection Functions (Arrays or Objects) 【集合函數】:java
一、#each# _.each(list, iterator, [context])正則表達式
迭代list中的全部元素,按順序用迭代器輸出每一個元素。若是傳遞了context參數,則把iterator綁定到context對象上。每次調用iterator都會傳遞三個參數:(element, index, list)
。若是list是個JavaScript對象,iterator的參數是(value, key, list)
。存在原生的forEach方法,Underscore就委託給forEach.編程
_.each([1, 2, 3], function(num){ console.log(num); });
// 1,2,3
_.each({one : 1, two : 2, three : 3}, function(num, key){ console.log(num); });
// 1,2,3
// html:
var p = document.getElementsByTagName(‘p’);json
_.each(p , function( value, key, list ){
console.log( value ); // p1,p2,p2
console.log( key ); // 0,1,2
})
二、#map# _.map(list, iterator, [context])數組
用轉換函數把list中的每一個值映射到一個新的數組。若是list是個JavaScript對象,iterator的參數是(value, key, list)
,這裏的用法和each
同樣。 map
和 each
的區別就是map
能夠接受返回值。瀏覽器
var r = _.map([1, 2, 3], function(num){ return num * 3; });
console.log(r); // [3, 6, 9]
var r = _.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
console.log(r); // [3, 6, 9]
三、#reduce# _.reduce(list, iterator, memo, [context])app
reduce方法把列表中元素歸結爲一個簡單的數值,Memo是reduce函數的初始值,reduce的每一步都須要由iterator返回。curl
var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
// 6
這個函數有些瀏覽器提供了原生的,可是對不知道的童鞋,可能很難經過這個例子明白函數的試用方法,好的,看源碼:
// 代碼的前面就聲明瞭一個變量,檢測是否支持原生reduce:
var nativeReduce = ArrayProto.reduce;
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduce && obj.reduce === nativeReduce) {
// 使用原生的reduce
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
each(obj, function(value, index, list) {
if (!initial) {
memo = value;
initial = true;
} else {
memo = iterator.call(context, memo, value, index, list);
}
});
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
return memo;
};
解釋上面的例子就是:試用迭代器把obj(1,2,3)裏面的元素相加,因爲設置了初始值(0),那就先加初始值,每次的相加的值都存儲在memo裏面。因此結果是0+1+2+3=6。
四、#reduceRight# _.reduceRight(list, iterator, memo, [context])
reducRight是從右側開始組合的元素的reduce函數,若是存在JavaScript 1.8版本的reduceRight,則用其代替。Foldr在javascript中不像其它有懶計算的語言那麼有用(lazy evaluation:一種求值策略,只有當表達式的值真正須要時纔對表達式進行計算)。
var list = [[0, 1], [2, 3], [4, 5]];
var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
=> [4, 5, 2, 3, 0, 1]
五、#find# _.find(list, iterator, [context])
遍歷list,返回第一個經過iterator真值檢測的元素值。若是找到匹配的元素當即返回,不會遍歷整個list。
var r = _.find([1, 2, 3, 4, 5, 6], function(num){
if(num > 3) return true;
});
// r == 4
六、#filter# _.filter(list, iterator, [context])
遍歷list,返回包含全部經過iterator真值檢測的元素值。若是存在原生filter方法,則委託給filter, 和find不一樣的是,它返回全部符合條件的值,返回一個數組。
var r = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
// r == [2, 4, 6]
七、#reject# _.reject(list, iterator, [context])
返回那麼沒有經過iterator真值檢測的元素數組,filter
的相反函數。
var r = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
//r == [1, 3, 5]
八、#all# _.all(list, iterator, [context])
若是list中的全部元素都經過iterator的真值檢測就返回true。若是存在原生的every方法,則委託給every。
var r = _.all([2, 22, 12, 4, 34, 68], function(num){ return num % 2 == 0; });
// r == true;
九、#any# _.any(list, [iterator], [context])
若是有任何一個元素經過經過 iterator 的真值檢測就返回true。若是存在原生的some方法,則委託給some。
var r = _.all([2, 1, 13, 6, 37, 68], function(num){ return num % 2 == 0; });
// r == true;
十、#contains# _.contains(list, value)
若是list包含指定的value則返回true,使用===檢測是否相等。若是list 是數組,內部使用indexOf判斷。
var r = _.contains([1, 2, 3], 3);
// r == true
_.contains({one:1,two:2},1);
// r == true
十一、#invoke#_.invoke(list, methodName, [*arguments])
在list的每一個元素上執行methodName方法。若是有額外的參數,則在調用methodName方法的時候傳給它。
_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
// [[1, 5, 7], [1, 2, 3]]
// 進行排序操做
十二、#pluck#_.pluck(list, propertyName)
提取對象中的一個屬性,返回一個數組。
var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
_.pluck(stooges, 'name');
// ["moe", "larry", "curly"]
1三、#max#_.max(list, [iterator], [context])
返回list中的最大值,迭代器可選,若是有,則以迭代器做爲排序依據。
var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
_.max(stooges, function(stooge){ return stooge.age; });
// {name : 'curly', age : 60};
1四、#min#_.min(list, [iterator], [context])
返回list中的最小值,迭代器可選,若是有,則以迭代器做爲排序依據。
var numbers = [10, 5, 100, 2, 1000];
_.min(numbers); // 2
1五、#sortBy#_.sortBy(list, iterator, [context])
返回一個經過升序排序後的一個數組(新的數組),若是有迭代器,以迭代器做爲排序依據。
_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
// [5, 4, 6, 3, 1, 2]
1六、#groupBy#_.groupBy(list, iterator)
經過迭代器返回的值分組,生成一個json對象。迭代器也能夠是一個字符串,經過調用元素對應的屬性分組。
_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
// {1: [1.3], 2: [2.1, 2.4]}
_.groupBy(['one', 'two', 'three'], 'length');
// {3: ["one", "two"], 5: ["three"]}
1七、#countBy#_.countBy(list, iterator)
對list進行分組,返回一個json對象,對應的鍵值對是:分組名(在迭代器裏面設置)和數量。
_.countBy([1, 2, 3, 4, 5], function(num) { return num % 2 == 0 ? 'even' : 'odd'; });
// {odd: 3, even: 2}
1八、#shuffle#_.shuffle(list)
返回一個打亂了的list數組副本。
_.shuffle([1, 2, 3, 4, 5, 6]);
// [4, 1, 6, 3, 5, 2]
1九、#toArray#_.toArray(list)
轉換list爲數組,對有參數對象的轉換頗有用。
(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
// [2, 3, 4]
20、#size#_.size(list)
返回list的長度
_.size({one:1,two:2}); // 2
2、Array Functions【數組函數】:
一、#first# _.first(array, [n])
返回array的第一個元素,設置了參數n,就返回前n個元素。
_.first([5, 4, 3, 2, 1]);
// 5
_.first([5,4,3,2,1],3);
// [5,4,3]
二、#last# _.last(array,[n])
返回list的最後一個元素,設置參數n,則返回最後n個元素。
_.last([5, 4, 3, 2, 1]);
// 1
_.last([5, 4, 3, 2, 1],2);
// [2,1]
三、#initial# _.initial(array, [n])
返回除了最後一個元素之外的全部元素。對參數對象特別有用。設置了參數n,就排除最後n個元素。
_.initial([5, 4, 3, 2, 1]);
// [5, 4, 3, 2]
_.initial([5, 4, 3, 2, 1] , 3);
// [5, 4]
四、#rest# _.rest(array, [index])
返回除了第一個元素之外的全部元素。設置了參數n,就排除前n個元素。
_.rest([5, 4, 3, 2, 1]);
// [4, 3, 2, 1]
_.rest([5, 4, 3, 2, 1],2);
// [3, 2, 1]
五、#compact# _.compact(array)
返回一個去除了false值的元素的數組副本。在javascript裏,false,null,0,「」,undefined,NaN是false值。
_.compact([0, 1, false, 2, '', 3]);
// [1, 2, 3]
六、#flatten# _.flatten(array, [shallow])
展開一個嵌套數組(能夠是任何嵌套級數),若是設置了參數shallow,就只能展開一個等級。
_.flatten([1, [2], [3, [[4]]]]);
// [1, 2, 3, 4];
_.flatten([1, [2], [3, [[4]]]], true);
// [1, 2, 3, [[4]]];
七、#without# _.without(array, [*values])
返回一個去處了values以後的數組副本。
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
// [2, 3, 4]
八、#union# _.union(*arrays)
計算傳入的 arrays(數組)並集:按順序返回一個存在於一個或多個 arrays(數組)中獨一無二的項目列表。
_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
// [1, 2, 3, 101, 10]
九、#intersection# _.intersection(*arrays)
計算數組的交集:每一個值都出如今每一個是數組裏。
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
// [1, 2]
十、#difference _.difference(array, *others)
和without差很少,不過它返回的是不在其餘數組裏面的值。
_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
// [1, 3, 4]
十一、#uniq# _.uniq(array, [isSorted], [iterator])
去除數組重複,使用===測試。若是你肯定數組已經排序,就傳遞true給isSorted。返回新的數組副本。
_.uniq([1, 2, 1, 3, 1, 4]);
// [1, 2, 3, 4]
十二、#zip# _.zip(*arrays)
在對應的位置合併每個數組元素,當你有單獨的有用數據源時經過匹配數組索引協調。若是您正在使用嵌套的數組矩陣,zip.apply能夠轉置矩陣類似的方式。
_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
// [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
1三、#object# _.object(list, [values])
把數組變成對象,能夠傳入鍵值對,也能夠傳入一個鍵數組,一個值數組。
_.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}
1四、#indexOf# _.indexOf(array, value, [isSorted])
返回值在數組裏面的索引,-1表示找不到。傳true給isSorted,表示數組已經排序,能夠提升速度。
_.indexOf([1, 2, 3], 2);
// 1
1五、#lastIndexOf# _.lastIndexOf(array, value, [fromIndex])
返回value在array最後開始的索引值,沒有則返回-1。
_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
// 4
1六、#sortedIndex# _.sortedIndex(list, value, [iterator])
運用二進制搜索,查找value在list裏面可插入的位置,傳true給isSorted,表示數組已經排序,能夠提升速度。
_.sortedIndex([10, 20, 30, 40, 50], 35);
// 3
1七、#range# _.range([start], stop, [step])
一個用來建立整數靈活編號的列表的函數,便於each 和 map循環。若是省略start則默認爲 0;step 默認爲 1.返回一個從start 到stop的整數的列表,用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);
// []
3、Functions 【函數】
一、#bind# _.bind(function, object, [*arguments])
綁定一個函數到一個對象上面,無論何時調用函數,this指針都是指向對象。也能夠爲函數綁定參數。
var func = function(greeting){ return greeting + ': ' + this.name };
func = _.bind(func, {name : 'moe'}, 'hi');
func();
// 'hi: moe'
二、#bindAll# _.bindAll(object, [*methodNames])
把methodNames參數指定的方法綁定到對象上,這些方法就會在對象的上下文環境中執行。綁定函數用做事件處理函數時很是便利,不然函數被調用時this一點用也沒有。若是不設置methodNames參數,對象上的全部方法都會被綁定。
var buttonView = {
label : 'underscore',
onClick : function(){ alert('clicked: ' + this.label); },
onHover : function(){ console.log('hovering: ' + this.label); }
};
_.bindAll(buttonView);
jQuery('#underscore_button').bind('click', buttonView.onClick);
// When the button is clicked, this.label will have the correct value...
三、#memoize# _.memoize(function, [hashFunction])
記錄函數的計算結果。對比較耗時的計算有幫助。若是設置了參數hashFunction,就用hashFunction的返回值做爲key存儲函數的計算結果。 hashFunction默認使用function的第一個參數做爲key.
var fibonacci = _.memoize(function(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
});
四、#delay# _.delay(function, wait, [*arguments])
和setTimeout差很少,在wait時間後調用函數,若是設置了參數,就在調用函數時,傳遞參數。
var log = _.bind(console.log, console);
_.delay(log, 1000, 'logged later');
// 'logged later'
五、#defer# _.defer(function, [*arguments])
延遲執行函數知道當前棧被清空,和delay爲0的setTimeout差很少。對HTML無阻賽渲染有幫助。若是設置了參數,就在函數調用時傳遞進去。
_.defer(function(){ alert('deferred'); });
// Returns from the function before the alert runs.
六、#throttle# _.throttle(function, wait)
建立並返回一個節流版本的函數,當重複調用函數時,就強制間隔wait時段才執行。
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);
七、#debounce# _.debounce(function, wait, [immediate])
建立並返回一個控制函數,當該函數被調用,wait毫秒後才執行,wait毫秒期間若是再次觸發則從新計時。
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
八、#once# _.once(function)
建立返回一個一次性函數。調用以後就不能再調用了。
var initialize = _.once(createApplication);
initialize();
initialize();
// Application is only created once.
九、#after# _.after(count, function)
建立返回一個函數,在這個函數別調用了count次以後,纔開始運行裏面的function。
var a = _.after(5,fun);
$(window).click(a);
十、#wrap# _.wrap(function, wrapper)
把第一個函數包裹在包裹器裏。
var hello = function(name) { return "hello: " + name; };
hello = _.wrap(hello, function(func) {
return "before, " + func("moe") + ", after";
});
hello();
// 'before, hello: moe, after'
十一、#compose# _.compose(*functions)
返回一個函數列的組合物,其中每一個函數的參數是其後跟隨函數的返回值。在數學關係上,f() g()和h()函數的組合產生f(g(h()))。
var greet = function(name){ return "hi: " + name; };
var exclaim = function(statement){ return statement + "!"; };
var welcome = _.compose(exclaim, greet);
welcome('moe');
// 'hi: moe!'
一、#keys# _.keys(object)
返回一個裝有object的鍵的數組
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
二、#values# _.values(object)
返回一個裝有object的值的數組
_.values({one : 1, two : 2, three : 3});
=> [1, 2, 3]
三、#pairs# _.pairs(object)
把對象的鍵值對轉變爲一個二維數組,並放到一個大的數組內
_.pairs({one: 1, two: 2, three: 3});
=> [["one", 1], ["two", 2], ["three", 3]]
四、#invert# _.invert(object)
複製一個對象,把object的鍵值反轉返回。
_.invert({Moe: "Moses", Larry: "Louis", Curly: "Jerome"}); => {Moses: "Moe", Louis: "Larry", Jerome: "Curly"};
五、#functions# _.functions(object)
返回一個數組,裏面裝有object的全部函數名稱
_.functions(_);
=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
六、#extend# _.extend(destination, *sources)
擴展,源對象將覆蓋或者建立目標對象的屬性
var a = {name : 'moe'}
_.extend(a, {age : 50});
=> a == {name : 'moe', age : 50}
七、#pick# _.pick(object, *keys)
經過keys從object選擇出鍵值對,放到一個新建的object返回
ps:keys也能夠是一個包含有效鍵的數組
_.pick({name : 'moe', age: 50, userid : 'moe1'}, 'name', 'age');
=> {name : 'moe', age : 50}
_.pick({name : 'moe', age: 50, userid : 'moe1'}, ['name', 'age']);
=> {name : 'moe', age : 50}
八、#omit# _.omit(object, *keys)
經過keys忽略object裏面的鍵值對,剩下的放入一個新建的對象返回。
ps:keys也能夠是一個包含有效鍵的數組,基本跟pick
相反
_.omit({name : 'moe', age : 50, userid : 'moe1'}, 'userid');
=> {name : 'moe', age : 50}
九、#defaults#
_.defaults(object,*defaults)
爲對象設置默認值,若是對象沒有設置值,則就調用默認值。
var iceCream = {flavor : "chocolate"};
_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
=> {flavor : "chocolate", sprinkles : "lots"}
十、
#clone# _.clone(object)
淺複製
_.clone({name : 'moe'});
=> {name : 'moe'};
十一、
#tap# _.tap(object ,interceptor)
摸索中
_.chain([1,2,3,200])
.filter(function(num) { return num % 2 == 0; })
.tap(alert)
.map(function(num) { return num * num })
.value();
=> // [2, 200] (alerted)
=> [4, 40000]
十二、
#has# _.has(object, key)
判斷object是否含有給出的key
_.has({a: 1, b: 2, c: 3}, "b");
=> true
1三、
#isEqual# _.isEqual(object, ohter)
深度對比了兩個object是否相等
var moe = {name : 'moe', luckyNumbers : [13, 27, 34]};
var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
moe == clone;
=> false
_.isEqual(moe, clone);
=> true
1四、
#isEmpty#_.isEmpty(object)
object是否爲空
_.isElement(jQuery('body')[0]);
=> true
1五、
#isArray# _.isArray(object)
object是否爲數組
(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
1六、
#isObject# _.isObject(object)
object是否爲對象
_.isObject({});
=> true
_.isObject(1);
=> false
1七、
#isArguments# _.isArguments(object)
object是否爲參數對象
(function(){ return _.isArguments(arguments); })(1, 2, 3);
=> true
_.isArguments([1,2,3]);
=> false
1八、
#isFunction#_.isFunction(object)
object是否爲函數
_.isFunction(alert);
=> true
1九、
#isString# _.isString(object)
object是否爲字符串
_.isString("moe");
=> true
20、
#isNumber# _.isNumber(object)
object是否爲數字
_.isNumber(8.4 * 5);
=> true
2一、
#isFinite# _.isFinite(object)
object是否爲有限數
_.isFinite(-101);
=> true
_.isFinite(-Infinity);
=> false
2二、
#isBoolean# _.isBoolean(object)
object是否爲布爾值
_.isBoolean(null);
=> false
2三、
#isDate# _.isDate(object)
object是否爲日期
_.isDate(new Date());
=> true
2四、
#isRegExp# _.isRegExp(object)
object是否爲正則表達式
_.isRegExp(/moe/);
=> true
2五、
#isNaN# _.isNaN(object)
object是否爲NaN
_.isNaN(NaN);
=> true
isNaN(undefined);
=> true
_.isNaN(undefined);
=> false
2六、
#isNull# _.isNull(object)
object是否爲Null
_.isNull(null);
=> true
_.isNull(undefined);
=> false
2七、
#isUndefined# _.isUndefined(object)
object是否爲undefined
_.isUndefined(window.missingVariable);
=> true