Lodash源码解析 Part1:Array、Collection
lodash究竟做了什么?
封装
封装可能会用到但是原生方法未提供的方法。
每当想要处理一个数组对象,但是原生方法没有,去lodash里总能找到。容错
类型判断,边界值等等
性能
遍历
结论:几乎全部是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 areThey 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
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
-
数组长度确定的时候,用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
不会更占内存么?
网友评论