摘要:遍歷中的所有元素,按順序用遍歷輸出每個(gè)元素。如果傳遞了參數(shù),則把綁定到對(duì)象上。返回以方便鏈?zhǔn)秸{(diào)用。
each _.each(list, iteratee, [context])?Alias:?forEach?
遍歷list中的所有元素,按順序用遍歷輸出每個(gè)元素。如果傳遞了context參數(shù),則把iteratee綁定到context對(duì)象上。每次調(diào)用iteratee都會(huì)傳遞三個(gè)參數(shù):(element, index, list)。如果list是個(gè)JavaScript對(duì)象,iteratee的參數(shù)是?(value, key, list))。返回list以方便鏈?zhǔn)秸{(diào)用。
_.each([1, 2, 3], alert); => alerts each number in turn... _.each({one: 1, two: 2, three: 3}, alert); => alerts each number value in turn...
_.each 源碼
// The cornerstone, an `each` implementation, aka `forEach`. // Handles raw objects in addition to array-likes. Treats all // sparse array-likes as if they were dense. _.each = _.forEach = function(obj, iteratee, context) { iteratee = optimizeCb(iteratee, context); var i, length; if (isArrayLike(obj)) { for (i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj); } } else { var keys = _.keys(obj); for (i = 0, length = keys.length; i < length; i++) { iteratee(obj[keys[i]], keys[i], obj); } } return obj; };
分析
_.each([1, 2, 3], alert); // _.each()使用方法,其中`alert`可以換成自己寫的function
obj 是[1, 2, 3] , iteratee 是alert , context 沒(méi)有
iteratee = optimizeCb(iteratee, context);
首先是調(diào)用optimizeCb()函數(shù)
分析 optimizeCb 源碼
var optimizeCb = function(func, context, argCount) { if (context === void 0) return func; };
因?yàn)?b>context 沒(méi)有,所以這里直接返回alert , 所以 iteratee 現(xiàn)在是alert
再使用 isArrayLike 判斷 傳進(jìn)來(lái)的obj是不是數(shù)組,判斷數(shù)組的方法
//原理就是通過(guò)判斷它是否具有長(zhǎng)度且長(zhǎng)度大于0且小于MAX_ARRAY_INDEX var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; var getLength = property("length"); var isArrayLike = function(collection) { var length = getLength(collection); return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX; };
因?yàn)檫@里是數(shù)組,所以繼續(xù)
// 通過(guò) for 循環(huán)來(lái)遍歷數(shù)組里面每一個(gè)值,傳給 iteratee 函數(shù)來(lái)運(yùn)行 for (i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj); // 等于 alert(obj[i], i, obj); }
如果不是數(shù)組呢?對(duì)象默認(rèn)是沒(méi)有length 屬性的
var keys = _.keys(obj); for (i = 0, length = keys.length; i < length; i++) { iteratee(obj[keys[i]], keys[i], obj); }
使用了_.keys() 函數(shù),下面分析 _keys() 源碼
_.keys = function(obj) { if (!_.isObject(obj)) return []; if (nativeKeys) return nativeKeys(obj); var keys = []; for (var key in obj) if (_.has(obj, key)) keys.push(key); // Ahem, IE < 9. if (hasEnumBug) collectNonEnumProps(obj, keys); return keys; };
首先使用_.isObject函數(shù)判斷是不是對(duì)象
// Is a given variable an object? _.isObject = function(obj) { var type = typeof obj; return type === "function" || type === "object" && !!obj; };
首先判斷傳進(jìn)來(lái)的參數(shù)的類型,然后返回true或者false
注意,通過(guò)以下兩個(gè)例子可知, && 的優(yōu)先級(jí)比 || 的高
console.log(true || false && false) // true console.log(true || false && true) // true
然后如果瀏覽器支持 ES5 的 Object.keys 方法,就優(yōu)先使用
nativeKeys = Object.keys,
不支持就繼續(xù)遍歷循環(huán) 對(duì)象
var keys = []; // own enumerable properties for (var key in obj) // hasOwnProperty if (_.has(obj, key)) keys.push(key);
使用了 _.has() 函數(shù),下面解析_.has()函數(shù)
// Shortcut function for checking if an object has a given property directly // on itself (in other words, not on a prototype). _.has = function(obj, key) { return obj != null && hasOwnProperty.call(obj, key); };
通過(guò)判斷 傳進(jìn)來(lái)的obj 是否為null 并且調(diào)用hasOwnProperty 方法判斷該對(duì)象是否有該鍵值
hasOwnProperty = ObjProto.hasOwnProperty = Object.prototype.hasOwnProperty;
如果有該屬性,返回true ,這時(shí)回到_.keys() ,該簡(jiǎn)直push 到keys[] 內(nèi)
// IE9以下不能用 for in 來(lái)遍歷,所以使用collectNonEnumProps()函數(shù)來(lái)解決問(wèn)題,暫時(shí)可以不看 if (hasEnumBug) collectNonEnumProps(obj, keys);
這時(shí)已經(jīng)把對(duì)象轉(zhuǎn)化成數(shù)組了,回到_.each() 函數(shù),繼續(xù)使用for 循環(huán)遍歷數(shù)組 ,把參數(shù)傳遞給alert函數(shù)
for (i = 0, length = keys.length; i < length; i++) { iteratee(obj[keys[i]], keys[i], obj); // 等于 alert(obj[keys[i]], keys[i], obj); }
最后再返回obj
整個(gè)分析_.each() 函數(shù),相繼分析了_.has() 和_.keys() 函數(shù),大概看了一下underscore.js 的源碼,感覺(jué)不是太難,一個(gè)函數(shù)一個(gè)函數(shù)分析就好。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80826.html
摘要:譯立即執(zhí)行函數(shù)表達(dá)式處理支持瀏覽器環(huán)境微信小程序。學(xué)習(xí)整體架構(gòu),利于打造屬于自己的函數(shù)式編程類庫(kù)。下一篇文章可能是學(xué)習(xí)的源碼整體架構(gòu)。也可以加微信,注明來(lái)源,拉您進(jìn)前端視野交流群。 前言 上一篇文章寫了jQuery整體架構(gòu),學(xué)習(xí) jQuery 源碼整體架構(gòu),打造屬于自己的 js 類庫(kù) 雖然看過(guò)挺多underscore.js分析類的文章,但總感覺(jué)少點(diǎn)什么。這也許就是紙上得來(lái)終覺(jué)淺,絕知此...
摘要:所以,剛開(kāi)始,我從源碼比較短的包含注釋只有行開(kāi)始學(xué)習(xí)起。一般,在客戶端瀏覽器環(huán)境中,即為,暴露在全局中。學(xué)習(xí)以后判斷直接使用看起來(lái)也優(yōu)雅一點(diǎn)滑稽臉。在的函數(shù)視線中,的作用執(zhí)行一個(gè)傳入函數(shù)次,并返回由每次執(zhí)行結(jié)果組成的數(shù)組。 前言 最近在社區(qū)瀏覽文章的時(shí)候,看到了一位大四學(xué)長(zhǎng)在尋求前端工作中的面經(jīng),看完不得不佩服,掌握知識(shí)點(diǎn)真是全面,無(wú)論是前端后臺(tái)還是其他,都有涉獵。 在他寫的文章中,有...
摘要:前面的的目的在于利用自定義拋出錯(cuò)誤令遍歷停止如果是數(shù)組直接過(guò)濾輸出不是數(shù)組遍歷操作壓入數(shù)組返回有點(diǎn)像,過(guò)濾符合條件的注意感嘆號(hào)取反有點(diǎn)像設(shè)置默認(rèn)迭代器判斷是否存在即需要所有元素都滿足迭代條件。 前言 這篇文章是為之后的underscore現(xiàn)版本的源碼做鋪墊,先感受下最先版本 0.1.0版本足夠小 這個(gè)版本已經(jīng)有將近小10年的歷史了 還是有一些不錯(cuò)的地方。 0.1.0版本源碼分析 ...
摘要:最近開(kāi)始看源碼,并將源碼解讀放在了我的計(jì)劃中。今天就跟大家聊一聊中一些常用類型檢查方法,以及一些工具類的判斷方法。用是否含有屬性來(lái)判斷工具類判斷方法接下來(lái)看下一些常用的工具類判斷方法。 Why underscore 最近開(kāi)始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。 閱讀一些著名框架類庫(kù)的源碼,就好像和一個(gè)個(gè)大師對(duì)話...
摘要:創(chuàng)建一個(gè)全局對(duì)象在瀏覽器中表示為對(duì)象在中表示對(duì)象保存下劃線變量被覆蓋之前的值如果出現(xiàn)命名沖突或考慮到規(guī)范可通過(guò)方法恢復(fù)被占用之前的值并返回對(duì)象以便重新命名創(chuàng)建一個(gè)空的對(duì)象常量便于內(nèi)部共享使用將內(nèi)置對(duì)象的原型鏈緩存在局部變量方便快速調(diào)用將 // Underscore.js 1.3.3 // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc....
閱讀 1195·2021-10-11 10:59
閱讀 1975·2021-09-29 09:44
閱讀 863·2021-09-01 10:32
閱讀 1437·2019-08-30 14:21
閱讀 1880·2019-08-29 15:39
閱讀 2986·2019-08-29 13:45
閱讀 3542·2019-08-29 13:27
閱讀 2015·2019-08-29 12:27