Lodash源码解析 Part1:Array、Collection

Lodash源码解析 Part1:Array、Collection

lodash究竟做了什么?

  • 封装

    封装可能会用到但是原生方法未提供的方法。
    每当想要处理一个数组对象,但是原生方法没有,去lodash里总能找到。

  • 容错

    类型判断,边界值等等

  • 性能

    http://jsben.ch/browse

遍历

结论:几乎全部是while……

举个例子

  function arrayMap(array, iteratee) {
    var index = -1,
        length = array == null ? 0 : array.length,
        result = Array(length);

    while (++index < length) {
      result[index] = iteratee(array[index], index, array);
    }
    return result;
  }
  • find,filter,slice,indexOf,forEach,filter,map,reduce等等,都是用while实现的

  • 多个数组间的并集交集差集等等,都是通过嵌套while实现的,并没有什么特别

  • 如果嵌套while,需要时使用continue label

All the results clearly shows that for loop are more proficient than for each than map/reduce/filter/find.
Map/Reduce/Filter/Find are slow because of many reason, some of them are

They have a call back to execute so that act as a overhead .
There are lot of corner cases that javascript function consider like getters, sparse array and checking arguments that are passed is array or not which adds up to overhead.

Note: If you’re using loops, always use them idiomatically since compilers are now smart enough to correctly optimize idiomatic loops
这句就像是看《正则表达式》,讲坑和避坑指南优化的时候,基本没有明确答案。原因是说,引擎一直在优化。

https://hackernoon.com/javascript-performance-test-for-vs-for-each-vs-map-reduce-filter-find-32c1113f19d7
https://github.com/dg92/Performance-Analysis-JS

  • join,reverse 原生方法

  • string 的indexOf还是用的indexOf

排序

Array:sortedIndex

二分查找

Collection:sort

while配合原生sort

稳定排序

原生sort(就地算法)非稳定,意即,equal的数据顺序不能保持不变。

https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.sort

同mdn,对多个排序规则的例子,先.map处理好,并且记录index(以此保持稳定排序)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

     * @returns {number} Returns the sort order indicator for `object`.
     */
    function compareMultiple(object, other, orders) {
      var index = -1,
          objCriteria = object.criteria,
          othCriteria = other.criteria,
          length = objCriteria.length,
          ordersLength = orders.length;

      while (++index < length) {
        var result = compareAscending(objCriteria[index], othCriteria[index]);
        if (result) {
          if (index >= ordersLength) {
            return result;
          }
          var order = orders[index];
          return result * (order == 'desc' ? -1 : 1);
        }
      }
      // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
      // that causes it, under certain circumstances, to provide the same value for
      // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
      // for more details.
      //
      // This also ensures a stable sort in V8 and other engines.
      // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
      return object.index - other.index;
    }

中文Mdn说现在是稳定的,在chrome测试确实是稳定的了

https://www.baidu.com/link?url=-Oh5B3APlWXYOgF3rpSIe5LBBbYYcL6n38MrOXfOVG1FHm_mFx4V3KUPDYWoqobOQ-BiJ_wgu3Y4ZoCM337edMJF9EoAwM5DR-AN-00luAFrNuW6KZhTfchSjKYbAcQ5ito9duaYnyI6vGVfVEwL4K&wd=&eqid=dad841cd00041613000000035cb8f5aa
https://blog.csdn.net/qq_18145031/article/details/82500177
https://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms

Set And Get

Array() vs new Array()

and vs []

    result = Array(5)
    result[0]=1;
    result[1]=2;

vs

    result = [];
    result.push(1)
    result.push(2)

https://stackoverflow.com/questions/8205691/array-vs-new-array

还引发了 https://stackoverflow.com/questions/383402/is-javascripts-new-keyword-considered-harmful 这种讨论

官方说法:When Array is called as a function rather than as a constructor, it also creates and initializes a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.

https://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-array-constructor

https://www.ecma-international.org/ecma-262/5.1/#sec-15.4.1

direct assign vs push

array[length+0]=value vs array.push(value)

lodash的例子

function arrayPush(array, values) {
    var index = -1,
        length = values.length,
        offset = array.length;

    while (++index < length) {
      array[offset + index] = values[index];
    }
    return array;
  }
  

http://jsben.ch/XOq7U 例子 assign direct faster than push

https://stackoverflow.com/questions/614126/why-is-array-push-sometimes-faster-than-arrayn-value 10年前……

https://stackoverflow.com/questions/42884123/appending-an-element-to-an-array-differences-between-direct-assignment-and-pus 2年前:push is doing a lot more work than assignment

https://stackoverflow.com/questions/559844/whats-better-to-use-in-php-array-value-or-array-pusharray-value

  • 数组长度确定的时候,用assign direct

  • 在数组长度未知的情况,有的时候用assign direct,有的时候会用push,I don't know why……

    两个例子

    function remove(array, predicate) {
      var result = [];
      if (!(array && array.length)) {
        return result;
      }
      var index = -1,
          indexes = [],
          length = array.length;
    
      predicate = getIteratee(predicate, 3);
      while (++index < length) {
        var value = array[index];
        if (predicate(value, index, array)) {
          result.push(value);
          indexes.push(index);
        }
      }
      basePullAt(array, indexes);
      return result;
    }
    
    function baseSortedUniq(array, iteratee) {
      var index = -1,
          length = array.length,
          resIndex = 0,
          result = [];
    
      while (++index < length) {
        var value = array[index],
            computed = iteratee ? iteratee(value) : value;
    
        if (!index || !eq(computed, seen)) {
          var seen = computed;
          result[resIndex++] = value === 0 ? 0 : value;//这个又是为什么? = value ===0 ? 0 : value 不就是相当于 = value;
        }
      }
      return result;
    }
    

类型

    this.__data__ = {
        'hash': new Hash,
        'map': new (Map || ListCache),
        'string': new Hash
      };

      ……

      function getMapData(map, key) {
      var data = map.__data__;
      return isKeyable(key)
        ? data[typeof key == 'string' ? 'string' : 'hash']
        : data.map;
    }

数组和数组用Hash
其他用Map

其他收获

  • result || (result = []) vs result = result ||[]

    减少一次没有必要的赋值

  • >>> vs /

    >>>0

    无符号右移,左边用0填充,永远非负:取整

    >>>1

    相当于/2,但做了取整、非负。在数组index的时候常用

  • concat(origin,...source)

    先将source concat成一个数组,然后再跟origin concat

    不会更占内存么?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,028评论 0 2
  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,448评论 0 13
  • Javascript有很多数组的方法,有的人有W3C的API,还可以去MDN上去找,但是我觉得API上说的不全,M...
    顽皮的雪狐七七阅读 4,071评论 0 6
  • <center>#1 Two Sum</center> link Description:Given an arr...
    铛铛铛clark阅读 2,143评论 0 3
  • 近些年来,关注自己的时候远远比关注别人的时候多。不管怎么说,我自己觉得这是个不好的习惯。一个人在原地打转,与走出去...
    扬思阅读 340评论 0 3