var arr = [1, 2, 3, 4, 5]; _.each(arr, function(el) { console.log(el); });
上面的代碼會依次輸出1, 2, 3, 4, 5,是否是頗有意思,遍歷一個數組連for循環都不用本身寫了。_.each()方法遍歷數組很是好用,可是它的內部實現一點都不難。下面就一塊兒來看看究竟是如何實現_.each()的。在這以前,咱們先來看看_.each()的API。_.each()的通常是以下調用的:數組
_.each(arr, fn, context);
它接收3個參數,瀏覽器
var _ = {}; // 假設這就是underscore哈 // 一個最簡單的_.each方法的實現 _.each = function(arr, fn) { for(var i = 0; i < arr.length; i++) { fn(arr[i], i, arr); } return arr; // 把原數組返回 }
怎麼樣?是否是很簡單呢?只是用一個for循環,不停的調用回調函數便可,短短几行代碼就搞定了,相信沒有朋友看不懂的哈!下面咱們來測試一下看能不能正常工做:app
var arr = [1, 2, 3, 4, 5]; _.each(arr, function(el, i, arr) { console.log(el); });
在瀏覽器打開,而後控制檯就會看到有正確的輸出了。函數
var arr = [1, 2, 3, 4, 5]; arr.sum = 0; // sum屬性用來存放數組元素之和 _.each(arr, function(el, i, arr) { this.sum += el; });
這時候,回調函數裏面用到了this,若是不綁定的話,this默認就是window,這不是咱們想要的,咱們但願它綁定到數組arr上面。call或者apply能夠實現這個功能,代碼以下:測試
var _ = {}; // 假設這就是underscore哈 // bind,接收兩個參數fn和context // 把fn綁定到context上面 var bind = function(fn, context) { context = context || null; return function(el, i, arr) { fn.call(context, el, i, arr); } } // _.each _.each = function(arr, fn, context) { // 調用bind方法,把fn綁定到context上面 fn = bind(fn, context); for(var i = 0; i < arr.length; i++) { fn(arr[i], i, arr); } return arr; } // 測試用例: var arr = [1, 2, 3, 4, 5]; arr.sum = 0; // sum屬性用來存放數組元素之和 _.each(arr, function(el, i, arr) { this.sum += el; }, arr); console.log(arr.sum); // 15
好啦,這個_.each()已經足夠強大了,能夠正常遍歷數組,還能夠任意指定this值改變回調函數的上下文。可是,咱們前面有提到過,Underscore的_.each()還能夠遍歷對象的 ,這個實現也不難,只要判斷一下傳入的第一個參數是對象仍是數組,若是是數組就像咱們同樣遍歷,不然若是是對象,使用對象的for...in循環遍歷就好了。有興趣的能夠本身試試,或者看看underscore的源碼。this