鲁迅说过:只有阅读过优秀库源码的人,才能配的上是真正的勇士。

compact

创建一个新数组,包含原数组中所有的非假值元素。例如false, null,0, “”, undefined, 和 NaN 都是被认为是“假值”。

注意以上的描述并不包括[],{}因为在js中,这个两个会进行隐式转换会把这两个值转换成为true。换句话来说该函数并不会去过滤这两个值。

官方代码:

export function compact(array){
let resIndex = 0;
const result = []
if(array == null){ // 会把undefined给排除掉 因为 undefined == null 为true
return result
}
for(const value of array){
if(value){
result[resIndex++] = value
}
}
return result
}

个人理解代码:

export function compact(array){
let resIndex = 0;
const result = []
if(array == null){ // 会把undefined给排除掉 因为 undefined == null 为true
return result
}
result = array.filter(v=>Boolean(v))
return result
}

直接利用filter进行遍历,利用boolean,来对元素进行真假转换。

concat

创建一个新数组,将array与任何数组 或 值连接在一起。

var array = [1];
var other = _.concat(array, 2, [3], [[4]]); console.log(other);
// => [1, 2, 3, [4]] console.log(array);
// => [1]

相对来说,concat函数所依赖的工具函数就多几个。

  1. arrayPush数组添加方法
  2. copyArray拷贝数组元素
  3. baseFlatten扁平层级数组
export function concat(){

let length = arguments.length; // 获取参数的个数
if (!length) {
return [];
}
let args = Array(length - 1); // 取除了第一个参数以外的参数的长度
let array = arguments[0]; // 取出数组的第一项
let index = length;
while (index--) {
args[index - 1] = arguments[index];
}
console.log(args); // 把第一个参数也就是目标数组,当作-1项添加为array
// 判断一个参数是否是数组,不是就把它转换成为数组,如果是数组则拷贝一份数组,再使用arrayPush方法,把每项的参数推进数组里面去。
return arrayPush(Array.isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
}

copyArray

拷贝数组,此操作不会影响到原有的数组。

参数 说明
soure 原数组参数
array 结果数组
export function copyArray(source,array){
let index = -1;
let length = source.length;
array || (array = Array(length));
while(++index < length){
array[index] = source[index]
}
return array
}

baseFlatten

该方法主要用于扁平数组的操作

export function baseFlatten(array, depth, predicate, isStrict, result) {
let index = -1;
let length = array.length;
predicate || (predicate = isFlattenable); // isFlattenable 判断是否是数组
result || (result = []);
while (++index < length) {
let value = array[index];
console.log(value);
if (depth > 0 && predicate(value)) { // 如果层级大于0并且该项是数组的话
if (depth > 1) { // 如果需要递归的层级大于1的情况则继续递归下去解套
baseFlatten(value, depth - 1, predicate, isStrict, result);
} else { // 如果需要递归的层级为1的情况,则把所有的项添加目标数组
arrayPush(result, value);
}
} else if (!isStrict) {
result[result.length] = value;
}
}
return result;
}
isFlattenable(value){
return Array.isArray(value)
}

发散思考,该函数只要是通过depth变量,来控制筛选的层级,那么我希望实现扁平所有的数组,那应该怎么操作呢?

function flattern(arr) {
return arr.reduce((cur, next) => cur.concat(Array.isArray(next) ? flattern(next) : next), []);
}

arrayPush

添加元素进入原数组,会改变原数组结构,类似push方法

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

总结

  1. ++index和index++不同之处,++i就是先加后用,i++就是先用后加。前置++下标不会越界,后置++下标越界。
  2. lodash库操作数组一般都不会影响原有数组。

阅读lodash源码之旅数组方法篇-compact和concat的更多相关文章

  1. 手把手带你阅读Mybatis源码(三)缓存篇

    前言 大家好,这一篇文章是MyBatis系列的最后一篇文章,前面两篇文章:手把手带你阅读Mybatis源码(一)构造篇 和 手把手带你阅读Mybatis源码(二)执行篇,主要说明了MyBatis是如何 ...

  2. lodash源码分析之数组的差集

    外部世界那些破旧与贫困的样子,可以使我内心世界得到平衡. --卡尔维诺<烟云> 本文为读 lodash 源码的第十七篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodas ...

  3. 手把手带你阅读Mybatis源码(一)构造篇

    前言 今天会给大家分享我们常用的持久层框架——MyBatis的工作原理和源码解析,后续会围绕Mybatis框架做一些比较深入的讲解,之后这部分内容会归置到公众号菜单栏:连载中…-框架分析中,欢迎探讨! ...

  4. 手把手带你阅读Mybatis源码(二)执行篇

    前言 上一篇文章提到了MyBatis是如何构建配置类的,也说了MyBatis在运行过程中主要分为两个阶段,第一是构建,第二就是执行,所以这篇文章会带大家来了解一下MyBatis是如何从构建完毕,到执行 ...

  5. 从源码角度看finish()方法的执行流程

    1. finish()方法概览 首先我们来看一下finish方法的无参版本的定义: /** * Call this when your activity is done and should be c ...

  6. lodash源码分析之获取数据类型

    所有的悲伤,总会留下一丝欢乐的线索,所有的遗憾,总会留下一处完美的角落,我在冰峰的深海,寻找希望的缺口,却在惊醒时,瞥见绝美的阳光! --几米 本文为读 lodash 源码的第十八篇,后续文章会更新到 ...

  7. 读lodash源码之从slice看稀疏数组与密集数组

    卑鄙是卑鄙者的通行证,高尚是高尚者的墓志铭. --北岛<回答> 看北岛就是从这两句诗开始的,高尚者已死,只剩卑鄙者在世间横行. 本文为读 lodash 源码的第一篇,后续文章会更新到这个仓 ...

  8. lodash源码分析之compact中的遍历

    小时候, 乡愁是一枚小小的邮票, 我在这头, 母亲在那头. 长大后,乡愁是一张窄窄的船票, 我在这头, 新娘在那头. 后来啊, 乡愁是一方矮矮的坟墓, 我在外头, 母亲在里头. 而现在, 乡愁是一湾浅 ...

  9. lodash源码分析之Hash缓存

    在那小小的梦的暖阁,我为你收藏起整个季节的烟雨. --洛夫<灵河> 本文为读 lodash 源码的第四篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash gitbo ...

随机推荐

  1. C#数据结构-赫夫曼树

    什么是赫夫曼树? 赫夫曼树(Huffman Tree)是指给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小.哈夫曼树(也称为最优二叉树)是带权路径长度最短的树,权值较大的结点 ...

  2. Boost.JSON Boost的JSON解析库(1.75首发)

    目录 目录 Boost的1.75版本新库 JSON库简介 JSON的简单使用 编码 最通用的方法 使用std::initializer_list json对象的输出 两种对比 解码 简单的解码 增加错 ...

  3. Python高级语法-import导入-sys.path(4.4.1)

    @ 目录 1.说明 2.代码 关于作者 1.说明 在开发程序的过程中,往往使用sys.path去验证下导入的目录,返回的是列表 先后顺序,就是扫描的先后顺序 ,也可以加入搜索路径 import有个特点 ...

  4. 多任务-python实现-同步概念,互斥锁解决资源竞争(2.1.4)

    @ 目录 1.同步的概念 2.解决线程同时修改全局变量的方式 3.互斥锁 1.同步的概念 同步就是协同步调,按照预定的先后次序进行运行,如你说完我在说 同步在子面上容易理解为一起工作 其实不是,同指的 ...

  5. PHPCMS V9.6.3的后台漏洞分析

    PHPCMS V9.6.3后台的漏洞分析 1.利用文件包含创建任意文件getshell 漏洞文件:\phpcmsv9\phpcms\modules\block\block_admin.php 漏洞产生 ...

  6. 任务队列--nodejs

    很多项目可能都会涉及到任务队列来进行任务处理和维护的,那么需要使用到redis或者第三方库(使用redis)来实现任务队列,甚至需要控制并发量,但是对于saas部署来说使用redis可能会比较麻烦和成 ...

  7. 中小学生的噩梦:怎样用Python检测抄袭行为?广大中小学生们的美梦就此结束

    本教程将介绍如何使用机器学习技术(如word2vec和余弦相似度等),在Python中用几行代码制作抄袭检测器.搭建完成后,抄袭检测器将会从文件中载入学生们的作业,然后通过计算相似度来判断学生有无相互 ...

  8. python爬虫之解析链接

    解析链接 1. urlparse() & urlunparse() urlparse() 是对url链接识别和分段的,API用法如下: urllib.parse.urlparse(urlstr ...

  9. BP暴力破解

    BurpSuite暴力破解 1.设置代理 首先要用phpstudy打开Mysql和Apache,然后将设置浏览器代理,地址127.0.0.1  端口8080 2.进入dvwa靶场 进入dvwa时,要用 ...

  10. Windows 64位下安装Redis 以及 可视化工具Redis Desktop Manager的安装和使用

    二.下载Windows版本的Redis 由于现在官网上只提供Linux版本的下载,所以我们只能在Github上下载Windows版本的Redis Windows版本的Redis下载地址:https:/ ...