一文搞懂:_.cloneDeep(value)

简介: 一文搞懂:_.cloneDeep(value)

119


.cloneDeep(value)


.cloneDeep与clone方法类似,cloneDeep会递归深度克隆一个对象


参数


value (): 需要递归深度克隆的值


返回值


(): 返回深度克隆好的值


例子


var objects = 【{ 'a': 1 }, { 'b': 2 }】;


var deep = .cloneDeep(objects);


console.log(deep【0】 === objects【0】);


// => false


源代码:


baseClone方法和.clone里的是同一个方法


import baseClone from './.internal/baseClone.js'


/ Used to compose bitmasks for cloning. */


const CLONE_DEEP_FLAG = 1


const CLONE_SYMBOLS_FLAG = 4


/


This method is like clone except that it recursively clones value.



@since 1.0.0


@category Lang


@param { } value The value to recursively clone.


@returns { } Returns the deep cloned value.


@see clone


@example



const objects = 【{ 'a': 1 }, { 'b': 2 }】



const deep = cloneDeep(objects)


console.log(deep【0】 === objects【0】)


// => false


/


//与clone方法类似,cloneDeep会递归深度克隆一个对象


function cloneDeep(value) {


return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG)


}


export default cloneDeep


baseClone


import Stack from './Stack.js'


import arrayEach from './arrayEach.js'


import assignValue from './assignValue.js'


import baseAssign from './baseAssign.js'


import baseAssignIn from './baseAssignIn.js'


import cloneBuffer from './cloneBuffer.js'


import copyArray from './copyArray.js'


import cloneArrayBuffer from './cloneArrayBuffer.js'


import cloneDataView from './cloneDataView.js'


import cloneRegExp from './cloneRegExp.js'


import cloneSymbol from './cloneSymbol.js'


import cloneTypedArray from './cloneTypedArray.js'


import copySymbols from './copySymbols.js'


import copySymbolsIn from './copySymbolsIn.js'


import getAllKeys from './getAllKeys.js'


import getAllKeysIn from './getAllKeysIn.js'


import getTag from './getTag.js'


import initCloneObject from './initCloneObject.js'


import isBuffer from '../isBuffer.js'


import isObject from '../isObject.js'


import keys from '../keys.js'


import keysIn from '../keysIn.js'


/** Used to compose bitmasks for cloning. /


//判断克隆的类型,使用二进制掩码标识了深克隆,浅克隆,展平克隆(将继承属性展平)


const CLONE_DEEP_FLAG = 1


const CLONE_FLAT_FLAG = 2


const CLONE_SYMBOLS_FLAG = 4


/ Object#toString result references. */


//对象的toStringTag


const argsTag = '【object Arguments】'


const arrayTag = '【object Array】'


const boolTag = '【object Boolean】'


const dateTag = '【object Date】'


const errorTag = '【object Error】'


const mapTag = '【object Map】'


const numberTag = '【object Number】'


const objectTag = '【object Object】'


const regexpTag = '【object RegExp】'


const setTag = '【object Set】'


const stringTag = '【object String】'


const symbolTag = '【object Symbol】'


const weakMapTag = '【object WeakMap】'


const arrayBufferTag = '【object ArrayBuffer】'


const dataViewTag = '【object DataView】'


const float32Tag = '【object Float32Array】'


const float64Tag = '【object Float64Array】'


const int8Tag = '【object Int8Array】'


const int16Tag = '【object Int16Array】'


const int32Tag = '【object Int32Array】'


const uint8Tag = '【object Uint8Array】'


const uint8ClampedTag = '【object Uint8ClampedArray】'


const uint16Tag = '【object Uint16Array】'


const uint32Tag = '【object Uint32Array】'


/ Used to identify toStringTag values supported by clone. /


//用来确定指定的toStringTag是否支持克隆


const cloneableTags = {}


cloneableTags【argsTag】 = cloneableTags【arrayTag】 =


cloneableTags【arrayBufferTag】 = cloneableTags【dataViewTag】 =


cloneableTags【boolTag】 = cloneableTags【dateTag】 =


cloneableTags【float32Tag】 = cloneableTags【float64Tag】 =


cloneableTags【int8Tag】 = cloneableTags【int16Tag】 =


cloneableTags【int32Tag】 = cloneableTags【mapTag】 =


cloneableTags【numberTag】 = cloneableTags【objectTag】 =


cloneableTags【regexpTag】 = cloneableTags【setTag】 =


cloneableTags【stringTag】 = cloneableTags【symbolTag】 =


cloneableTags【uint8Tag】 = cloneableTags【uint8ClampedTag】 =


cloneableTags【uint16Tag】 = cloneableTags【uint32Tag】 = true


cloneableTags【errorTag】 = cloneableTags【weakMapTag】 = false


/** Used to check objects for own properties. /


//用于检测是否是对象自身的属性


const hasOwnProperty = Object.prototype.hasOwnProperty


/


Initializes an object clone based on its toStringTag.



* Note: This function only supports cloning values with tags of


Boolean, Date, Error, Map, Number, RegExp, Set, or String.



@private


@param {Object} object The object to clone.


@param {string} tag The toStringTag of the object to clone.


@param {boolean} 【isDeep】 Specify a deep clone.


//代码效果参考:http://www.jhylw.com.cn/170622997.html

@returns {Object} Returns the initialized clone.

/


//基于toStringTag初始化对象克隆


//注意:此方法只支持如下类型:Boolean, Date, Error, Map, Number, RegExp, Set, or String.


function initCloneByTag(object, tag, isDeep) {


const Ctor = object.constructor//object的构造函数


switch (tag) {


case


return cloneArrayBuffer(object)


case


case


return new Ctor(+object)


case


return cloneDataView(object, isDeep)


case float32Tag: case float64Tag:


case int8Tag: case int16Tag: case int32Tag:


case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:


//Float32Array Float64Array Int8Array Int16Array Int32Array Uint8Array Uint8ClampedArray Uint16Array Uint32Array


return cloneTypedArray(object, isDeep)


case


return new Ctor


case numberTag:


case stringTag:


//Number String


return new Ctor(object)


case


return cloneRegExp(object)


case


return new Ctor


case


return cloneSymbol(object)


}


}


/


Initializes an array clone.



@private


@param {Array} array The array to clone.


@returns {Array} Returns the initialized clone.


/


//初始化数组的克隆,返回一个初始化的克隆结果,就是和原数组长度一样的但是元素都为空位的数组


function initCloneArray(array) {


const { length } = array//数组的长度


const result = new array.constructor(length)//初始化结果数组


// Add properties assigned by RegExp#exec.


//将正则方法exec()返回的数组的index和input属性克隆到结果数组上


if (length && typeof array【0】 == 'string' && hasOwnProperty.call(array, 'index')) {


result.index = array.index


result.input = array.input


}


return result


}


/*


The base implementation of clone and cloneDeep which tracks


traversed objects.



@private


@param { } value The value to clone.


@param {number} bitmask The bitmask flags.


1 - Deep clone


2 - Flatten inherited properties


4 - Clone symbols


@param {Function} 【customizer】 The function to customize cloning.


@param {string} 【key】 The key of value.


@param {Object} 【object】 The parent object of value.


@param {Object} 【stack】 Tracks traversed objects and their clone counterparts.


@returns { } Returns the cloned value.


/


//clone和cloneDeep的基础实现


function baseClone(value, bitmask, customizer, key, object, stack) {


let result//克隆的结果


const isDeep = bitmask & CLONE_DEEP_FLAG//是否是深度克隆


const isFlat = bitmask & CLONE_FLAT_FLAG//是否是展开继承属性的克隆


const isFull = bitmask & CLONE_SYMBOLS_FLAG//是否是浅克隆


if (customizer) {//如果传递了自定义克隆方法,用自定义的克隆方法处理


result = object ? customizer(value, key, object, stack) : customizer(value)


}


if (result !== undefined) {//如果自定义克隆处理后能够result有变化,直接返回结果


return result


}


if (!isObject(value)) {//判断要克隆的值是否不是对象是简单值,如果是简单值直接返回


return value


}


const isArr = Array.isArray(value)//判断value是否是array


const tag = getTag(value)//获取value的toStringTag


if (isArr) {//如果value是数组


result = initCloneArray(value)


//初始化克隆数组,返回一个初始化的克隆结果,就是和原数组长度一样的但是元素都为空位的数组


if (!isDeep) {//如果是浅克隆,调用copyArray处理


return copyArray(value, result)


}


} else {//如果value不是数组


const isFunc = typeof value == 'function'//判断value是否是function类型


if (isBuffer(value)) {//如果value是buffer对象


return cloneBuffer(value, isDeep)//使用cloneBuffer克隆buffer对象


}


if (tag == objectTag || tag == argsTag || (isFunc && !object)) {


//如果value的类型是Object arguments 或者是函数并且没有父级对象包裹


result = (isFlat || isFunc) ? {} : initCloneObject(value)


//初始化克隆结果,如果需要展开继承属性或者value是function,那初始化为空对象,否则调用initCloneObject处理


if (!isDeep) {//如果不是深度克隆


//先将普通属性克隆,然后再克隆symbol属性


return isFlat


? copySymbolsIn(value, baseAssignIn(result, value))


: copySymbols(value, baseAssign(result, value))


}


} else {


if (isFunc || !cloneableTags【tag】) {


//其他情况如果是有父级对象的function或者不支持克隆的类型


return object ? value : {}//返回value或者空对象


}


result = initCloneByTag(value, tag, isDeep)


//根据toStringTag来初始化克隆


}


}


// Check for circular references and return its corresponding clone.


//检查循环引用并且返回对应的克隆


stack || (stack = new Stack)//用来存放键值对的数据结构


const stacked = stack.get(value)//获取stack中的value对应的result


if (stacked) {//如果stack中存在直接返回


return stacked


}


stack.set(value, result)//设置value对应result到stack中


if (tag == mapTag) {//如果是map数据类型


value.forEach((subValue, key) => {//循环map复制到result上,递归调用baseClone复制其中的值


result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack))


})


return result


}


if (tag == setTag) {//如果是set数据类型


value.forEach((subValue) => {//循环set复制到result上,递归调用baseClone复制其中的值


result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack))


})


return result


}


if (isTypedArray(value)) {//如果是typedArray直接返回结果


return result


}


const keysFunc = isFull


? (isFlat ? getAllKeysIn : getAllKeys)


: (isFlat ? keysIn : keys)//获取对象key数组的方法根据是否需要展平继承属性使用不同的


const props = isArr ? undefined : keysFunc(value)//获取键组成的数组


arrayEach(props || value, (subValue, key) => {//循环键数组,将值复制


if (props) {


key = subValue


subValue = value【key】


}


// Recursively populate clone (susceptible to call stack limits).


//递归克隆其值是复杂对象的情况,容易受到调用栈大小限制的影响


assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack))


})


return result


}


export default baseClone

相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3 )前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解   课程大纲 第一章 了解数据仓库概念 初步了解数据仓库是干什么的 第二章 按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章 数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章 采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章 用户行为数据仓库 严格按照企业的标准开发 第六章 搭建业务数仓理论基础和对表的分类同步 第七章 业务数仓的搭建  业务行为数仓效果图  
相关文章
|
JavaScript 前端开发 安全
抽象语法树(AST):理解JavaScript代码的抽象语法树
抽象语法树(AST):理解JavaScript代码的抽象语法树
|
JavaScript
js截取,拼接,字符串方法
js截取,拼接,字符串方法
|
前端开发 Java 调度
springboot整合SSE技术开发经验总结及心得
springboot整合SSE技术开发经验总结及心得
3504 0
Java 将Map的toString格式字符串转为 Map
Java 将Map的toString格式字符串转为 Map
1646 0
Java 将Map的toString格式字符串转为 Map
|
存储 前端开发 JavaScript
ahooks 正式发布:值得拥抱的 React Hooks 工具库
ahook定位于一套基于 React Hooks 的工具库,核心围绕 React Hooks 的逻辑封装能力,降低代码复杂度和避免团队的重复建设为背景,共同建设和维护阿里经济体层面的 React Hooks 库。
24285 1
ahooks 正式发布:值得拥抱的 React Hooks 工具库
|
11月前
|
存储 弹性计算 安全
阿里云服务器ECS实例选购参考:vCPU到云盘IOPS等指标详解
阿里云服务器ECS实例可以分为多种实例规格族,而根据CPU、内存等配置的不同,一种实例规格族又进一步细分为多种实例规格。这些实例规格包含了众多关键的性能指标,如 vCPU、处理器、内存、vTPM、本地存储、网络带宽、网络收发包 PPS、连接数、弹性网卡、云盘带宽、云盘 IOPS 等。深入理解这些性能指标,对于用户在阿里云服务器购买过程中选择最适合自己业务需求的实例规格至关重要。
|
9月前
|
存储 JavaScript 前端开发
element ui <el-date-picker> 设置展示当前月
在 Element UI 中,使用 `el-date-picker` 的 `value-format` 属性可将日期值格式化为指定字符串。设置 `type=&quot;month&quot;` 时,绑定值默认为 Date 对象,通过 `value-format=&quot;yyyy-MM&quot;` 可将其转为如 &quot;2023-05&quot; 格式,便于存储与处理。
1435 0
|
存储 Swift 对象存储
OpenStack的对象存储(Swift)
【8月更文挑战第24天】
721 1
|
JavaScript 前端开发 安全
深入探索JavaScript中的structuredClone:现代深拷贝的解密指南
深入探索JavaScript中的structuredClone:现代深拷贝的解密指南
478 0
|
JSON JavaScript 前端开发
Unexpected token u in JSON at position 0
这篇文章解释了JavaScript中"Unexpected token u in JSON at position 0"错误的常见原因,通常是由于尝试解析undefined变量导致的,并建议检查是否有变量在JSON.parse()执行时未赋值或值为undefined。
Unexpected token u in JSON at position 0

热门文章

最新文章