30 underscore

underscore
	js第三方庫
		jQuery統一了不一樣瀏覽器之間的DOM操做的差別,讓咱們能夠簡單地對DOM進行操做
		underscore則提供了一套完善的函數式編程的接口,讓咱們更方便地在JavaScript中實現函數式編程

	爲何叫underscore
		jQuery在加載時,會把自身綁定到惟一的全局變量$上
		underscore與其相似,會把自身綁定到惟一的全局變量_上,這也是爲啥它的名字叫underscore的緣由

	原型就是類
		underscore爲集合類對象提供了一致的接口。集合類是指Array和Object,暫不支持Map和Set。
		var obj = {
			name: 'bob',
			school: 'No.1 middle school',
			address: 'xueyuan road'
		};

	map/filter
		和Array的map()與filter()相似
		underscore的map()和filter()能夠做用於Object
		看成用於Object時,傳入的函數爲function (value, key),第一個參數接收value,第二個參數接收key
			var upper = _.map(obj, function (value, key) {
				return key+":"+value;
			});//["name:bob","school:No.1 middle school","address:xueyuan road"]返回結果是Array

			var upper = _.mapObject(obj, function (value, key) {
				return key+":"+value;
			});//{"name":"name:bob","school":"school:No.1 middle school","address":"address:xueyuan road"}返回結果是Object
			
	every / some
		_.every():當集合的全部元素都知足條件時,函數返回true
		_.some(),當集合的至少一個元素知足條件時,函數返回true
			// 全部元素都大於0?
			_.every([1, 4, 7, -3, -9], (x) => x > 0); // false
			// 至少一個元素大於0?
			_.some([1, 4, 7, -3, -9], (x) => x > 0); // true
			
	max / min
		這兩個函數直接返回集合中最大和最小的數:
			var arr = [3, 5, 7, 9];
			_.max(arr); // 9
			_.min(arr); // 3
			傳入參數是Object,max()和min()只做用於value,忽略掉key:
				'use strict';
				_.max({ a: 1, b: 2, c: 3 }); // 3
	groupBy
		groupBy()把集合的元素按照key歸類,key由傳入的函數返回
			var scores = [20, 81, 75, 40, 91, 59, 77, 66, 72, 88, 99];
			var groups = _.groupBy(scores, function (x) {
				if (x < 60) {
					return 'C';
				} else if (x < 80) {
					return 'B';
				} else {
					return 'A';
				}
			});
			
	shuffle / sample
			shuffle()用洗牌算法隨機打亂一個集合:
				.shuffle([1, 2, 3, 4, 5, 6]); // [3, 5, 4, 6, 2, 1]
			sample()則是隨機選擇一個或多個元素:
				   // 隨機選1個:
					_.sample([1, 2, 3, 4, 5, 6]); // 2
					// 隨機選3個:
					_.sample([1, 2, 3, 4, 5, 6], 3); // [6, 1, 4]

underscore爲Array提供了許多工具類方法
Arrays
	first()/ last()
		顧名思義,這兩個函數分別取第一個和最後一個元素		
			var arr = [2, 4, 6, 8];
			_.first(arr); // 2
			_.last(arr); // 8
	flatten()
		flatten()接收一個Array,不管這個Array裏面嵌套了多少個Array,flatten()最後都把它們變成一個一維數組:
		'use strict';
		_.flatten([1, [2], [3, [[4], [5]]]]); // [1, 2, 3, 4, 5]
		
	zip / unzip
		zip()把兩個或多個數組的全部元素按索引對齊,而後按索引合併成新數組。
		var names = ['Adam', 'Lisa', 'Bart'];
		var scores = [85, 92, 59];
		_.zip(names, scores);// [['Adam', 85], ['Lisa', 92], ['Bart', 59]]
		
		var namesAndScores = [['Adam', 85], ['Lisa', 92], ['Bart', 59]];
		_.unzip(namesAndScores);
		// [['Adam', 'Lisa', 'Bart'], [85, 92, 59]]
	
	object
		有時候你會想,與其用zip(),爲啥不把名字和分數直接對應成Object呢?別急,object()函數就是幹這個的
		var names = ['Adam', 'Lisa', 'Bart'];
		var scores = [85, 92, 59];
		_.object(names, scores);
		// {Adam: 85, Lisa: 92, Bart: 59}
		
	range
		range()讓你快速生成一個序列,再也不須要用for循環實現了:
		// 從0開始小於10:
		_.range(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
		// 從1開始小於11:
		_.range(1, 11); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
		// 從0開始小於30,步長5:
		_.range(0, 30, 5); // [0, 5, 10, 15, 20, 25]
function
	提供了大量JavaScript自己沒有的高階函數
bind
	call()的做用是把this和對象綁定起來,而後執行函數
	結論:當用一個變量fn指向一個對象的方法時,直接調用fn()是不行的,由於丟失了this對象的引用。用bind能夠修復這個問題。
	    var s = ' Hello  ';
		var fn = _.bind(s.trim, s);
		fn();// 輸出Hello
		fn指向對象s的trim方法,fn中的this綁定s
		
partial
	partial()就是爲一個函數建立偏函數
	建立偏函數的目的是將原函數的某些參數固定住,能夠下降新函數調用的難度。
		var pow2N = _.partial(Math.pow, 2);
		pow2N(3); // 8
		
不想固定第一個參數,想固定第二個參數
		var cube = _.partial(Math.pow, _, 3);//_做佔位符
		cube(3); // 27
		
memoize
	若是一個函數調用開銷很大,咱們就可能但願能把結果緩存下來,以便後續調用時直接得到結果
		var factorial = _.memoize(function(n) {
			console.log('start calculate ' + n + '!...');
			var s = 1, i = n;
			while (i > 1) {
				s = s * i;
				i --;
			}
			console.log(n + '! = ' + s);
			return s;
		});
		
once
	顧名思義,once()保證某個函數執行且僅執行一次
		var register = _.once(function () {
			alert('Register ok!');
		});
		
delay
	delay()可讓一個函數延遲執行,效果和setTimeout()是同樣的
	_.delay(alert, 2000);
	若是要延遲調用的函數有參數,把參數也傳進去
		var log = _.bind(console.log, console);
		_.delay(log, 2000, 'Hello,', 'world!');
		// 2秒後打印'Hello, world!':


提供了大量針對Object的函數
Objects
	keys / allKeys
		keys()能夠很是方便地返回一個object自身全部的key,但不包含從原型鏈繼承下來的
			function Student(name, age) {
			this.name = name;
			this.age = age;
			}

			var xiaoming = new Student('小明', 20);
			_.keys(xiaoming); // ['name', 'age']
		allKeys()除了object自身的key,還包含從原型鏈繼承下來的:
			_.allKeys(xiaoming); // ['name', 'age', 'school']
	values
		values()返回object自身但不包含原型鏈繼承的全部值
	mapObject
		mapObject()就是針對object的map版本
	invert
		invert()把object的每一個key-value交換位置,key變成value,value變成key
		_.invert(obj); // { '59': 'Bart', '85': 'Lisa', '90': 'Adam' }

	extend / extendOwn
		extend()把多個object的key-value合併到第一個object並返回:
			_.extend(a, {age: 15}, {age: 88, city: 'Beijing'}); // {name: 'Bob', age: 88, city: 'Beijing'}
			注意:若是有相同的key,後面的object的value將覆蓋前面的object的value。
			extendOwn()和extend()相似,但獲取屬性時忽略從原型鏈繼承下來的屬性
	clone
		clone():複製一個object對象,它會把原有對象的全部屬性都複製到新的對象中
			意,clone()是「淺複製」。所謂「淺複製」就是說,兩個對象相同的key所引用的value實際上是同一對象:
			也就是說,修改source.skills會影響copied.skills
	isEqual
		isEqual()對兩個object進行深度比較,若是內容徹底相同,則返回true
			_.isEqual(o1, o2); // true  支持對象和數組

Chaining
chain():把對象包裝成能進行鏈式調用的方法
	鏈式調用,原理是每一個方法return this,一個對象後面跟着多個點
	$('a').attr('target', '_blank')
		  .append(' <i class="uk-icon-external-link"></i>')
		  .click(function () {});
		  
	var r = _.chain([1, 4, 9, 16, 25])
         .map(Math.sqrt)
         .filter(x => x % 2 === 1)
         .value();
	  
	由於每一步返回的都是包裝對象,因此最後一步的結果須要調用value()得到最終結果
相關文章
相關標籤/搜索