摘要:接收三個參數(shù)分別為回調(diào)和,其中與是可選參數(shù)。官網(wǎng)釋義排序一個列表組成一個組,并且返回各組中的對象的數(shù)量的計(jì)數(shù)。類似,但是不是返回列表的值,而是返回在該組中值的數(shù)目。
繼續(xù)前面的內(nèi)容,前文我們提到了很多方法的講解,其實(shí)到這里就已經(jīng)差不多了,因?yàn)榇蟛糠执a其實(shí)都是套路,一些基礎(chǔ)函數(shù)再靈活變化就可以組成很多實(shí)用的功能。
_.sortBy = function(obj, iteratee, context) { var index = 0; iteratee = cb(iteratee, context); return _.pluck(_.map(obj, function(value, key, list) { return { value: value, index: index++, criteria: iteratee(value, key, list) }; }).sort(function(left, right) { var a = left.criteria; var b = right.criteria; if (a !== b) { if (a > b || a === void 0) return 1; if (a < b || b === void 0) return -1; } return left.index - right.index; }), "value"); };
_.sortBy,顧名思義這是一個對數(shù)組進(jìn)行排序處理的函數(shù),在原生 JAVASCRIPT 中 sort() 的詳情可參考 Array.prototype.sort()、TypedArray.prototype.sort()。_.sortBy 接收三個參數(shù)分別為 obj、iteratee 回調(diào)和 context,其中 iteratee 與 context 是可選參數(shù)。
當(dāng)傳入值只有 obj 時(shí),應(yīng)該限定 obj 類型為數(shù)組且值為 Number,為什么呢,這里涉及到 JAVASCRIPT 對數(shù)字字符串的比較的問題了,JAVASCRIPT 在進(jìn)行字符串比較的時(shí)候遵循的是二進(jìn)制與運(yùn)算,也就是說并不是數(shù)字 length 越長就會大于 length 小的。舉個栗子:
_.sortBy([1, 2, 3, 4, 5, 6, 8, 7, 11, 13]); [1, 2, 3, 4, 5, 6, 7, 8, 11, 13] _.sortBy(["1", "2", "3", "4", "5", "6", "8", "7", "11", "13"]); ["1", "11", "13", "2", "3", "4", "5", "6", "7", "8"]
同學(xué)們都很聰明,不用我在說了,言歸正傳,當(dāng)只有 obj 一個值且值為 Number,那么默認(rèn)從左到右從小到大排序,為什么呢,我看下代碼,在 _.pluck 中代碼只做了一件事,就是整理數(shù)據(jù),當(dāng)沒有 iteratee 的時(shí)候執(zhí)行 cb 函數(shù)里的 if (value == null) return _.identity; 也就是相當(dāng)于默認(rèn) iteratee function 為 _.identity 即 return obj,所以 _.map 中回調(diào)的 criteria 值即 value。有點(diǎn)繞口,代碼起開(假定只有 obj 一個參數(shù)):
_.sortBy = function(obj) { var index = 0; return _.pluck(_.map(obj, function(value, key, list) { return { value: value, index: index++, criteria: (function(value, key, list) { return value; })(value, key, list); }; }).sort(function(left, right) { var a = left.criteria; var b = right.criteria; if (a !== b) { if (a > b || a === void 0) return 1; if (a < b || b === void 0) return -1; } return left.index - right.index; }), "value"); };
這樣看上去就直白好多。整理完數(shù)據(jù)之后就是 arr.sort([compareFunction]) 進(jìn)行排序,這里不說了。當(dāng)傳入?yún)?shù)有 iteratee 回調(diào)的時(shí)候,依舊老套路優(yōu)化回調(diào),然后根據(jù)回調(diào)函數(shù)里面的設(shè)定決定 criteria 參數(shù)值,criteria 參數(shù)是 arr.sort([compareFunction]) 進(jìn)行排序的關(guān)鍵標(biāo)識,so一定要是 Number才行。
var group = function(behavior, partition) { return function(obj, iteratee, context) { var result = partition ? [[], []] : {}; iteratee = cb(iteratee, context); _.each(obj, function(value, index) { var key = iteratee(value, index, obj); behavior(result, value, key); }); return result; }; };
group 是一個內(nèi)部函數(shù),我覺得它最特別在于將回調(diào)稱之為一個 behavior,為什么呢,因?yàn)殡m然 behavior function 只能被動接受 value, index, obj 三個參數(shù)進(jìn)行數(shù)值運(yùn)算,但作者巧妙的用它結(jié)合 group 包裝出 _.groupBy、_.indexBy、_.countBy、_.partition 四個函數(shù),在實(shí)際開發(fā)中我們處理數(shù)據(jù)時(shí)可能需要各種適用場景的工具,那么把如何函數(shù)寫好寫活呢,group 給了我很大的啟發(fā),言歸正傳,group 的 behavior 回調(diào)是在外部定義,源碼到這里并不知道 behavior 是什么東西,所以先一帶而過。
_.groupBy = group(function(result, value, key) { if (_.has(result, key)) result[key].push(value); else result[key] = [value]; });
_.groupBy 官網(wǎng)定義把一個集合分組為多個集合,通過 iterator 返回的結(jié)果進(jìn)行分組. 如果 iterator 是一個字符串而不是函數(shù), 那么將使用 iterator 作為各元素的屬性名來對比進(jìn)行分組.。
———————— 頹廢的分割線 ————————
從昨天到今天狀態(tài)不佳,昏天黑地的看了兩天電影,看到最后都不知道自己在看什么,我需要吐槽一下小米路由器,由于我是 linux 系統(tǒng),作為 deiban 死忠黨來說一臺不到兩千元的臺式機(jī)想要鏈接無線網(wǎng)絡(luò),折騰的時(shí)間和金錢都不如再填個路由器做中繼劃算,于是我買了這貨 小米路由器,它在路由器模式下還算可以,一但調(diào)整到中繼模式,這完全就是一個入坑的神展開,啪啪啪的隨時(shí)無間歇性斷網(wǎng)沒商量,莫名其妙的就連不上網(wǎng)了,即使連接上網(wǎng)絡(luò)網(wǎng)速都不如無線的一般有木有,在過去的一段時(shí)間里我有 N 次想把這款路由器摔在地上(額,或者摔在墻上),希望大家不要吐槽我兩千塊都不到的臺式主力機(jī),價(jià)錢雖然 lower 了點(diǎn),但性能絕對夠用,對于 mac 黨們我很希望大家轉(zhuǎn)粉,雖然我也有 mac 但是我平均開機(jī)數(shù)目大約在 1/(1~2個月)。
寫到這里目測大約水了一百多個文字,繼續(xù)前天的講解 ╮(╯Д╰)╭ 。
———————— END ————————
官網(wǎng)的意思是什么呢,假如我有一個 obj,那么我可以使用 _.groupBy 函數(shù)將這個 obj 通過其內(nèi)部值的某個屬性進(jìn)行分類,而這個屬性值的判斷也可以通過回調(diào)進(jìn)行擴(kuò)展斷言。那么當(dāng) iteratee 為 null 時(shí),_.groupBy 默認(rèn)使用前面的 group 函數(shù)中的 cb 函數(shù)的 if (value == null) return _.identity; 處理 iteratee 為空的情況,我來簡化一下 _.groupBy:
_.groupBy = function(obj) { var result = partition ? [[], []] : {}; _.each(obj, function(value, index) { var key = value; if (_.has(result, key)) result[key].push(value); else result[key] = [value]; }) return result; }
這樣理解是不是淺顯很多呢,設(shè)置 result 空數(shù)組,然后 _.each 遍歷 obj,滿滿的都是套路有木有,唯一亮點(diǎn)的地方就是 if 判斷是根據(jù) _.has 函數(shù)確定 result 中是否已經(jīng)存在 key-value。但是這里面還有一個更深的套路,那就是作者沒有對 obj 作進(jìn)一步處理,所以 _.groupBy 函數(shù)只能適用于 Array,舉個栗子:
_.groupBy(["one", "two", "three"]); {"one":["one"],"two":["two"],"three":["three"]} _.groupBy([{a:"one"}, {b:"two"}, {c:"three"}]); {"[object Object]":[{"a":"one"},{"b":"two"},{"c":"three"}]}
然后我們再說一下 _.groupBy 參數(shù)有第二個參數(shù)的情況,這里可以看出 cb 函數(shù)的重要性,它對 iteratee 的類型情況做了細(xì)致的判斷和處理,我們前面可以知道 cb 函數(shù)除了 Null、Function、Object 意外的類型都用 _.property 處理,即 生成獲取屬性值的函數(shù),那么我們傳參為數(shù)組呢,see ↓↓↓
_.groupBy(["one", "two", "three"],[1,2,3]) {"false":["one","two","three"]}
也就是說作者雖然大才,但是并沒有對超出范圍的值類型做進(jìn)一步的處理,也就是說 iteratee 的可選值類型只能為 Function 和 String。當(dāng)然這并不是錯,從工具的角度來講我們應(yīng)用函數(shù)應(yīng)該遵守函數(shù)創(chuàng)造者設(shè)定的規(guī)則,超出規(guī)則后出現(xiàn)錯誤并不是說作者的函數(shù)一定有問題,也可能是我們太過于調(diào)皮了(比如番茄西紅柿需要用平底鍋來炒,但廚師非要用電飯煲,這是廚師的錯還是平底鍋生產(chǎn)商的錯 ─=≡Σ((( つ??ω??)つ)。
言歸正傳當(dāng)傳入合理的 iteratee 值時(shí),其實(shí)整個函數(shù)的重點(diǎn)還是 group 函數(shù)內(nèi)部的 cb 函數(shù),因?yàn)槲覀兛梢钥丛创a _.groupBy 上的回調(diào)最終是落實(shí)到 cb 上,將一個函數(shù)比作一個公共房間,眾多人就是傳入傳出的參數(shù),那么 cb 就是門禁卡識別每個人的身份并發(fā)身份牌。如果 iteratee 是 String 則用 _.property 處理恰到好處(生成獲取屬性值的函數(shù)),如果是 Function 也只是在 if (_.has(result, key)) result[key].push(value); else result[key] = [value]; 之前通過回調(diào)生成相應(yīng)的 key 值。
_.indexBy = group(function(result, value, key) { result[key] = value; });
官網(wǎng)釋義 給定一個list,和 一個用來返回一個在列表中的每個元素鍵 的iterator 函數(shù)(或?qū)傩悦祷匾粋€每一項(xiàng)索引的對象。關(guān)鍵代碼參考 _.groupBy,二者的二區(qū)別也之有一行代碼,理解起來并不難,我就不再水文字了。
_.countBy = group(function(result, value, key) { if (_.has(result, key)) result[key]++; else result[key] = 1; });
官網(wǎng)釋義 排序一個列表組成一個組,并且返回各組中的對象的數(shù)量的計(jì)數(shù)。類似groupBy,但是不是返回列表的值,而是返回在該組中值的數(shù)目。其實(shí)就是對匹配成功的元素計(jì)數(shù)。
var reStrSymbol = /[^ud800-udfff]|[ud800-udbff][udc00-udfff]|[ud800-udfff]/g;
reStrSymbol 用于正則函數(shù),這一塊我也不是很熟悉,但是我找到了兩篇文章做了參考,Unicode Regular Expressions, Surrogate Points and UTF-8、
Re: Java char and Unicode 3.0+ (was:Canonical equivalence in rendering: mandatory or recommended?)、unicode。另外知乎上也有人對這句話做了判斷:
[^ud800-udfff] 普通的 BMP 字符,表示不包含代理對代碼點(diǎn)的所有字符 [ud800-udbff][udc00-udfff] 成對的代理項(xiàng)對,表示合法的代理對的所有字符 [ud800-udfff] 未成對的代理項(xiàng)字,表示代理對的代碼點(diǎn)(本身不是合法的Unicode字符)
以上僅供參考,我也不是很清楚,等我做好這方面功課的時(shí)候再重新說這個話題。
_.toArray = function(obj) { if (!obj) return []; if (_.isArray(obj)) return slice.call(obj); if (_.isString(obj)) { return obj.match(reStrSymbol); } if (isArrayLike(obj)) return _.map(obj, _.identity); return _.values(obj); };
官網(wǎng)說 把list(任何可以迭代的對象)轉(zhuǎn)換成一個數(shù)組,在轉(zhuǎn)換 arguments 對象時(shí)非常有用,并給出一個 (function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);,說心里話每當(dāng)看到 arguments 的時(shí)候我第一個印象是 Array.prototype.slice.call(arguments, indexes);,這里作者對待 Array 的原理同樣是這個。_.toArray 函數(shù)本身沒有重點(diǎn),無非就是根據(jù)字符串、數(shù)組、對象進(jìn)行數(shù)組轉(zhuǎn)換,需要注意的是當(dāng)轉(zhuǎn)換 Object 的時(shí)候會忽略 key-value 的 key,只多帶帶把 value 放到數(shù)組中,另外就是 if (_.isArray(obj)) 和 if (isArrayLike(obj)),顧名思義第一個是判斷數(shù)組,第二個難道是考慮到 {"length":[1,2,3,4]} 這種數(shù)據(jù)結(jié)構(gòu)的情況?
_.size = function(obj) { if (obj == null) return 0; return isArrayLike(obj) ? obj.length : _.keys(obj).length; };
_.size 用于返回傳入?yún)?shù)的長度,包括但不限于 Object、Array 、 String 和 Function,F(xiàn)unction 返回的是 Function 中傳入?yún)?shù)的個數(shù)(arguments)。另外 Map 這里有個坑,Map返回值是12,眾所周知 Map是一個大的對象,所以返回值是它的12個基本屬性的個數(shù)。
_.partition = group(function(result, value, pass) { result[pass ? 0 : 1].push(value); }, true);
_.partition 是第四個用 group 函數(shù)包裝的函數(shù),用來對傳入 obj 做判斷時(shí)返回符合回調(diào)斷言的結(jié)果集以及不符合的結(jié)果集,從 result[pass ? 0 : 1].push(value) 這里就可見一斑了,也就是說 group 的第三個傳參 partition 也就是為了 _.partition 而存在。partition 使 result 的設(shè)定為固定的 [[][]],這種寫法我覺得并不是看上去最優(yōu)雅地,理想情況是最好不存在第三個參數(shù)才對,但這一定是相對節(jié)約性能的,面對可節(jié)約的性能怎么取舍已經(jīng)很清楚了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86345.html
摘要:組件的選擇命令行工具首先我們需要一個命令行工具來方便的執(zhí)行命令,這里我們選擇組件,如果不喜歡使用且有能力的人完全可以通過組件自己封裝執(zhí)行命令函數(shù)。 對于一個成熟的項(xiàng)目而言,一定需要一個注釋文檔生成工具,我們有很多可選的開源項(xiàng)目,如jsdoc、yuidocjs 等等,擁有這些強(qiáng)大的工具我們完全可以勝任任何注釋方面的管理了么? 一個成熟的開發(fā)者都會知道不管怎么樣的項(xiàng)目都會在不同的開發(fā)條件下...
摘要:第四個判斷如果是對象執(zhí)行返回一個斷言函數(shù),用來判定傳入對象是否匹配指定鍵值屬性。都不匹配最后執(zhí)行,返回傳入的對象的屬性。設(shè)置的值并生成函數(shù),等同于,使具有屬性且有值則返回,否則返回,這是一個判斷函數(shù)。 在第二小章節(jié)里面我按照源碼順序介紹幾個方法,源碼緊接著第一章繼續(xù): var builtinIteratee; builtinIteratee,內(nèi)置的 Iteratee (迭代器)。...
摘要:新出臺的則規(guī)定,包括六種原始類型和,還有一種,詳見數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)。用于返回一個由給定對象的所有可枚舉自身屬性的屬性名組成的數(shù)組,。接下來判斷數(shù)字進(jìn)行相應(yīng)的操作,其中有和兩個方法,詳見和。 一直想寫一篇這樣的文章,于是心動不如行動,這里選擇的是 Underscore.js 1.8.3 版本,源碼注釋加在一起1625行。 Underscore.js 1.8.3 http://unde...
摘要:傳入值進(jìn)行判斷以此決定函數(shù),將三個參數(shù)包括回調(diào)傳入中其中回調(diào)函數(shù)充當(dāng)?shù)鬟M(jìn)行真值檢測,最后。是從一個中隨機(jī)返回值,并且返回值受限于這個參數(shù),如果沒有傳入或者傳入了則執(zhí)行語句,目的是將判斷處理之后返回單一值。 今天繼續(xù)上次的內(nèi)容,之前我們講到了 reduce 的用法,其實(shí)我覺得用法倒是其次的關(guān)鍵是作者實(shí)現(xiàn) reduce 過程中所靈活用到的函數(shù)處理方法,我們只要有心稍加總覺完全可以拿來主...
摘要:用來構(gòu)成和兩個函數(shù),主要針對的是為了將函數(shù)調(diào)用模式更改為構(gòu)造器調(diào)用和方法調(diào)用。通過函數(shù)設(shè)定時(shí)間為毫秒后執(zhí)行函數(shù)的回調(diào)函數(shù),用以達(dá)到在規(guī)定時(shí)間毫秒時(shí)執(zhí)行函數(shù)的目的,并且規(guī)定時(shí)間內(nèi)只執(zhí)行一次函數(shù)。 北京的雨已經(jīng)斷斷續(xù)續(xù)下了好久,昏昏欲睡的躲在家里不愿意出門,火影忍者快要結(jié)束了,一拳超人第二季據(jù)說還要等好多年,勇者大冒險(xiǎn)貌似斷更了,我又是在不喜歡海賊王的畫風(fēng),所以,我該看什么好呢。 va...
閱讀 2640·2021-11-22 15:24
閱讀 1370·2021-11-17 09:38
閱讀 2748·2021-10-09 09:57
閱讀 1193·2019-08-30 15:44
閱讀 2439·2019-08-30 14:00
閱讀 3539·2019-08-30 11:26
閱讀 2936·2019-08-29 16:28
閱讀 746·2019-08-29 13:56