美文网首页
Lodash源码解析 Part1:Array、Collectio

Lodash源码解析 Part1:Array、Collectio

作者: monvhh | 来源:发表于2019-04-19 10:35 被阅读0次

    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

      不会更占内存么?

    相关文章

      网友评论

          本文标题:Lodash源码解析 Part1:Array、Collectio

          本文链接:https://www.haomeiwen.com/subject/cwhfgqtx.html