国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

1625行,解開 underscore.js 的面紗 - 第四章

zhaochunqi / 1698人閱讀

摘要:接收三個參數分別為回調和,其中與是可選參數。官網釋義排序一個列表組成一個組,并且返回各組中的對象的數量的計數。類似,但是不是返回列表的值,而是返回在該組中值的數目。

繼續前面的內容,前文我們提到了很多方法的講解,其實到這里就已經差不多了,因為大部分代碼其實都是套路,一些基礎函數再靈活變化就可以組成很多實用的功能。

  _.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,顧名思義這是一個對數組進行排序處理的函數,在原生 JAVASCRIPT 中 sort() 的詳情可參考 Array.prototype.sort()、TypedArray.prototype.sort()。_.sortBy 接收三個參數分別為 obj、iteratee 回調和 context,其中 iteratee 與 context 是可選參數。
當傳入值只有 obj 時,應該限定 obj 類型為數組且值為 Number,為什么呢,這里涉及到 JAVASCRIPT 對數字字符串的比較的問題了,JAVASCRIPT 在進行字符串比較的時候遵循的是二進制與運算,也就是說并不是數字 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"]

同學們都很聰明,不用我在說了,言歸正傳,當只有 obj 一個值且值為 Number,那么默認從左到右從小到大排序,為什么呢,我看下代碼,在 _.pluck 中代碼只做了一件事,就是整理數據,當沒有 iteratee 的時候執行 cb 函數里的 if (value == null) return _.identity; 也就是相當于默認 iteratee function 為 _.identity 即 return obj,所以 _.map 中回調的 criteria 值即 value。有點繞口,代碼起開(假定只有 obj 一個參數):

   _.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");
   };

這樣看上去就直白好多。整理完數據之后就是 arr.sort([compareFunction]) 進行排序,這里不說了。當傳入參數有 iteratee 回調的時候,依舊老套路優化回調,然后根據回調函數里面的設定決定 criteria 參數值,criteria 參數是 arr.sort([compareFunction]) 進行排序的關鍵標識,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 是一個內部函數,我覺得它最特別在于將回調稱之為一個 behavior,為什么呢,因為雖然 behavior function 只能被動接受 value, index, obj 三個參數進行數值運算,但作者巧妙的用它結合 group 包裝出 _.groupBy_.indexBy_.countBy_.partition 四個函數,在實際開發中我們處理數據時可能需要各種適用場景的工具,那么把如何函數寫好寫活呢,group 給了我很大的啟發,言歸正傳,group 的 behavior 回調是在外部定義,源碼到這里并不知道 behavior 是什么東西,所以先一帶而過。

  _.groupBy = group(function(result, value, key) {
    if (_.has(result, key)) result[key].push(value); else result[key] = [value];
  });

_.groupBy 官網定義把一個集合分組為多個集合,通過 iterator 返回的結果進行分組. 如果 iterator 是一個字符串而不是函數, 那么將使用 iterator 作為各元素的屬性名來對比進行分組.

———————— 頹廢的分割線 ————————

從昨天到今天狀態不佳,昏天黑地的看了兩天電影,看到最后都不知道自己在看什么,我需要吐槽一下小米路由器,由于我是 linux 系統,作為 deiban 死忠黨來說一臺不到兩千元的臺式機想要鏈接無線網絡,折騰的時間和金錢都不如再填個路由器做中繼劃算,于是我買了這貨 小米路由器,它在路由器模式下還算可以,一但調整到中繼模式,這完全就是一個入坑的神展開,啪啪啪的隨時無間歇性斷網沒商量,莫名其妙的就連不上網了,即使連接上網絡網速都不如無線的一般有木有,在過去的一段時間里我有 N 次想把這款路由器摔在地上(額,或者摔在墻上),希望大家不要吐槽我兩千塊都不到的臺式主力機,價錢雖然 lower 了點,但性能絕對夠用,對于 mac 黨們我很希望大家轉粉,雖然我也有 mac 但是我平均開機數目大約在 1/(1~2個月)。

寫到這里目測大約水了一百多個文字,繼續前天的講解 ╮(╯Д╰)╭ 。

———————— END ————————

官網的意思是什么呢,假如我有一個 obj,那么我可以使用 _.groupBy 函數將這個 obj 通過其內部值的某個屬性進行分類,而這個屬性值的判斷也可以通過回調進行擴展斷言。那么當 iteratee 為 null 時,_.groupBy 默認使用前面的 group 函數中的 cb 函數的 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;
}

這樣理解是不是淺顯很多呢,設置 result 空數組,然后 _.each 遍歷 obj,滿滿的都是套路有木有,唯一亮點的地方就是 if 判斷是根據 _.has 函數確定 result 中是否已經存在 key-value。但是這里面還有一個更深的套路,那就是作者沒有對 obj 作進一步處理,所以 _.groupBy 函數只能適用于 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 參數有第二個參數的情況,這里可以看出 cb 函數的重要性,它對 iteratee 的類型情況做了細致的判斷和處理,我們前面可以知道 cb 函數除了 Null、Function、Object 意外的類型都用 _.property 處理,即 生成獲取屬性值的函數,那么我們傳參為數組呢,see ↓↓↓

 _.groupBy(["one", "two", "three"],[1,2,3])
 {"false":["one","two","three"]}

也就是說作者雖然大才,但是并沒有對超出范圍的值類型做進一步的處理,也就是說 iteratee 的可選值類型只能為 Function 和 String。當然這并不是錯,從工具的角度來講我們應用函數應該遵守函數創造者設定的規則,超出規則后出現錯誤并不是說作者的函數一定有問題,也可能是我們太過于調皮了(比如番茄西紅柿需要用平底鍋來炒,但廚師非要用電飯煲,這是廚師的錯還是平底鍋生產商的錯 ─=≡Σ((( つ??ω??)つ)。

言歸正傳當傳入合理的 iteratee 值時,其實整個函數的重點還是 group 函數內部的 cb 函數,因為我們可以看源碼 _.groupBy 上的回調最終是落實到 cb 上,將一個函數比作一個公共房間,眾多人就是傳入傳出的參數,那么 cb 就是門禁卡識別每個人的身份并發身份牌。如果 iteratee 是 String 則用 _.property 處理恰到好處(生成獲取屬性值的函數),如果是 Function 也只是在 if (_.has(result, key)) result[key].push(value); else result[key] = [value]; 之前通過回調生成相應的 key 值。

  _.indexBy = group(function(result, value, key) {
    result[key] = value;
  });

官網釋義 給定一個list,和 一個用來返回一個在列表中的每個元素鍵 的iterator 函數(或屬性名),返回一個每一項索引的對象。關鍵代碼參考 _.groupBy,二者的二區別也之有一行代碼,理解起來并不難,我就不再水文字了。

  _.countBy = group(function(result, value, key) {
    if (_.has(result, key)) result[key]++; else result[key] = 1;
  });

官網釋義 排序一個列表組成一個組,并且返回各組中的對象的數量的計數。類似groupBy,但是不是返回列表的值,而是返回在該組中值的數目。其實就是對匹配成功的元素計數。

  var reStrSymbol = /[^ud800-udfff]|[ud800-udbff][udc00-udfff]|[ud800-udfff]/g;

reStrSymbol 用于正則函數,這一塊我也不是很熟悉,但是我找到了兩篇文章做了參考,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 字符,表示不包含代理對代碼點的所有字符
 [ud800-udbff][udc00-udfff] 成對的代理項對,表示合法的代理對的所有字符
 [ud800-udfff] 未成對的代理項字,表示代理對的代碼點(本身不是合法的Unicode字符)

以上僅供參考,我也不是很清楚,等我做好這方面功課的時候再重新說這個話題。

  _.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);
  };

官網說 把list(任何可以迭代的對象)轉換成一個數組,在轉換 arguments 對象時非常有用,并給出一個 (function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);,說心里話每當看到 arguments 的時候我第一個印象是 Array.prototype.slice.call(arguments, indexes);,這里作者對待 Array 的原理同樣是這個。_.toArray 函數本身沒有重點,無非就是根據字符串、數組、對象進行數組轉換,需要注意的是當轉換 Object 的時候會忽略 key-value 的 key,只多帶帶把 value 放到數組中,另外就是 if (_.isArray(obj))if (isArrayLike(obj)),顧名思義第一個是判斷數組,第二個難道是考慮到 {"length":[1,2,3,4]} 這種數據結構的情況?

  _.size = function(obj) {
    if (obj == null) return 0;
    return isArrayLike(obj) ? obj.length : _.keys(obj).length;
  };

_.size 用于返回傳入參數的長度,包括但不限于 Object、Array 、 String 和 Function,Function 返回的是 Function 中傳入參數的個數(arguments)。另外 Map 這里有個坑,Map返回值是12,眾所周知 Map是一個大的對象,所以返回值是它的12個基本屬性的個數。

  _.partition = group(function(result, value, pass) {
    result[pass ? 0 : 1].push(value);
  }, true);

_.partition 是第四個用 group 函數包裝的函數,用來對傳入 obj 做判斷時返回符合回調斷言的結果集以及不符合的結果集,從 result[pass ? 0 : 1].push(value) 這里就可見一斑了,也就是說 group 的第三個傳參 partition 也就是為了 _.partition 而存在。partition 使 result 的設定為固定的 [[][]],這種寫法我覺得并不是看上去最優雅地,理想情況是最好不存在第三個參數才對,但這一定是相對節約性能的,面對可節約的性能怎么取舍已經很清楚了。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86345.html

相關文章

  • 如何自制 JS 注釋文檔生成工具

    摘要:組件的選擇命令行工具首先我們需要一個命令行工具來方便的執行命令,這里我們選擇組件,如果不喜歡使用且有能力的人完全可以通過組件自己封裝執行命令函數。 對于一個成熟的項目而言,一定需要一個注釋文檔生成工具,我們有很多可選的開源項目,如jsdoc、yuidocjs 等等,擁有這些強大的工具我們完全可以勝任任何注釋方面的管理了么? 一個成熟的開發者都會知道不管怎么樣的項目都會在不同的開發條件下...

    Cristalven 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第二章

    摘要:第四個判斷如果是對象執行返回一個斷言函數,用來判定傳入對象是否匹配指定鍵值屬性。都不匹配最后執行,返回傳入的對象的屬性。設置的值并生成函數,等同于,使具有屬性且有值則返回,否則返回,這是一個判斷函數。 在第二小章節里面我按照源碼順序介紹幾個方法,源碼緊接著第一章繼續: var builtinIteratee; builtinIteratee,內置的 Iteratee (迭代器)。...

    yuxue 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第一章

    摘要:新出臺的則規定,包括六種原始類型和,還有一種,詳見數據類型和數據結構。用于返回一個由給定對象的所有可枚舉自身屬性的屬性名組成的數組,。接下來判斷數字進行相應的操作,其中有和兩個方法,詳見和。 一直想寫一篇這樣的文章,于是心動不如行動,這里選擇的是 Underscore.js 1.8.3 版本,源碼注釋加在一起1625行。 Underscore.js 1.8.3 http://unde...

    MockingBird 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第三章

    摘要:傳入值進行判斷以此決定函數,將三個參數包括回調傳入中其中回調函數充當迭代器進行真值檢測,最后。是從一個中隨機返回值,并且返回值受限于這個參數,如果沒有傳入或者傳入了則執行語句,目的是將判斷處理之后返回單一值。 今天繼續上次的內容,之前我們講到了 reduce 的用法,其實我覺得用法倒是其次的關鍵是作者實現 reduce 過程中所靈活用到的函數處理方法,我們只要有心稍加總覺完全可以拿來主...

    dack 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第六章

    摘要:用來構成和兩個函數,主要針對的是為了將函數調用模式更改為構造器調用和方法調用。通過函數設定時間為毫秒后執行函數的回調函數,用以達到在規定時間毫秒時執行函數的目的,并且規定時間內只執行一次函數。 北京的雨已經斷斷續續下了好久,昏昏欲睡的躲在家里不愿意出門,火影忍者快要結束了,一拳超人第二季據說還要等好多年,勇者大冒險貌似斷更了,我又是在不喜歡海賊王的畫風,所以,我該看什么好呢。 va...

    v1 評論0 收藏0

發表評論

0條評論

zhaochunqi

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<