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

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. Redis 基础知识点总结

    关系型数据库 VS 非关系型数据库(NoSQL) 关系型数据库 我们过去使用的 mysql.Oracle 都属于关系型数据库.关系型数据库的特点是数据表之间可以存在联系,表内每列数据也存在关联,同时支 ...

  2. Hive中的集合数据类型

    除了使用础的数据类型string等,Hive中的列支持使用struct, map, array集合数据类型. 数据类型 描述 语法示例 STRUCT 和C语言中的struct或者"对象&qu ...

  3. go-slice实现的使用和基本原理

    目录 摘要 Slice数据结构 使用make创建Slice 使用数组创建Slice Slice 扩容 Slice Copy 特殊切片 总结 参考 你的鼓励也是我创作的动力 Posted by 微博@Y ...

  4. SpringBoot从入门到精通教程(二)

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...

  5. Django入门实战一

    前言 Django是高水准的Python编程语言驱动的一个开源模型.视图,控制器风格的Web应用程序框架,它起源于开源社区.使用这种架构,程序员可以方便.快捷地创建高品质.易维护.数据库驱动的应用程序 ...

  6. java基础:方法的定义和调用详细介绍,方法同时获取数组最大值和最小值,比较两个数组,数组交换最大最小值,附练习案列

    1. 方法概述 1.1 方法的概念 方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集 注意: 方法必须先创建才可以使用,该过程成为方法定义 方法创建后并不是直接可 ...

  7. 如何在iOS设备中配置S/MIME邮件签名证书

    本篇将介绍如何在iOS设备(如iPhone或iPad)上导入.配置并使用S/MIME邮件证书. 前置条件: iOS设备上已完成邮箱账号配置: 您的S/MIME邮件证书PFX/P12文件已导出备用. 步 ...

  8. python序列(二)列表的删除操作

    1.使用del命令删除列表中的指定位置上的元素 >>> s=[1,2,3,4] >>> del s[1] >>> s [1, 3, 4] 2.使用 ...

  9. 服务器挂掉导致需要对k8s新增节点

    [导读]今日是周六,本想午休起来之后写篇有关kubernetes service的文章,没想到两台虚拟机接连挂掉,所以又重新创建了两台虚拟机.新建时又一直黑屏,所以只能克隆. 由于虚拟机是新建的,所以 ...

  10. 使用OpenOffice实现文档预览

    概述 使用OpenOffice将 office文档转为pdf,然后再将pdf转为图片,实现文档预览的功能. 依赖组件 OpenOffice.org或者LibreOffice JODConverter ...