You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Returns a new Buffer that references the same memory as the original
While TypedArray#slice() creates a copy of part of the TypedArray, Buffer#slice() creates a view over the existing Buffer without copying.
文档清楚说明了 slice 是 without copying 的,为什么 lodash 会用作深拷贝呢?
本文实现方法都是看效果倒推实现方法,并进行一些拓展和思考,和源码无关。lodash这个库在这里更像一个题库,给我们刷题的
能收获什么:
注意:
clone & cloneDeep(不考虑不常用对象)
lodash除了常用的数据类型拷贝外,还会对各种奇怪对象进行拷贝。在实现lodash的之前,我们先实现一个正常的满足大部分场景的拷贝:
浅拷贝
深拷贝
clone & cloneDeep(考虑各种对象)
_.clone(value)
创建一个 value 的浅拷贝。_.cloneDeep(value)
创建一个 value 的深拷贝。baseClone(value, CLONE_SYMBOLS_FLAG)
,cloneDeep是baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG)
,此外,cloneDeepWith
函数也是baseClone
实现,此时baseClone
基于还多了第三个参数customizer
,是一个函数(customizer(value, key)
),对深拷贝前的值做预处理。下面我们要实现baseClone
方法各种对象及类型
Buffer
为了使 Buffer 实例的创建更可靠且更不容易出错,各种形式的 new Buffer() 构造函数都已被弃用,且改为单独的 Buffer.from(),Buffer.alloc() 和 Buffer.allocUnsafe() 方法。
Buffer的实例方法
slice
:buffer.slice([start[, end]])
,返回一个新的 Buffer,它引用与原始的 Buffer 相同的内存,但是由 start 和 end 索引进行偏移和裁剪。克隆buffer的方法:
ArrayBuffer
ArrayBuffer
对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象或 DataView 对象来操作DataView
上面提了一下dataview
其实dataview一些api和类型化数组(Float32Array, Float64Array, Int8Array, Int16Array, Int32Array, Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array)很像,套路都是一样的,所以拷贝类型化数组直接改一下函数就ok
RegExp
拷贝正则的时候,只需要读取他的source以及其他各种模式即可
因此克隆正则代码也很简单,但是要特别注意

lastIndex
在加了g
的匹配模式下的坑:Symbol
symbol类型的值,通过
Symbol(value)
产生,而且Symbol不能new。因此,克隆对象型的Symbol怎么办呢(如new Boolean、new Number这种手段产生的对象),其实只需要Object包一下即可,它的valueOf转换还是转换为正常的symbol
类型的值其他类型
如new出来的基本数据类型:Number、Boolean、String,也是直接重新new一下即可。Boolean需要注意:
!!new Boolean(false) === true
,但是+new Boolean(false) === 0
,所以new时转数字即可:new Boolean(+boolObj)
Date对象,也是直接new即可。不过为了安全起见可以先转成数字时间戳再new
至于Set、Map,重新new一个空的,然后一个个加进去。需要把递归后的结果加进去,因为加进去的元素也可能是复杂数据类型哦
数组克隆
数组初始化
初始化一般就定义一个空数组就行了。没错,的确是的。但是,还有一种特殊的数组,就是正则match返回的数组,具有index、input属性:
接下来就是克隆一个数组了,浅拷贝就直接返回
[...array]
,深拷贝数组的方法和普通对象一样的普通对象克隆
初始化对象initCloneObject
创建对象,我们都知道一个花括号字面量即可:
const o = {};
。但是,我们拷贝的时候,要考虑到继承的情况以及是不是原型对象获取所有的key
有了新对象,那么下一步就是从旧对象里面一个个key拷贝过来。对于key应该怎么拿,有几种case:
lodash里面,isFlat表示是否拷贝原型链,isFull表示是否拷贝symbol key,keysFunc返回一个数组,给后面遍历使用
根据我们的目的,我们要把4个获取key的方法实现出来。但是,在实现之前,先铺垫一下一些坑:
因此,实现代码如下:
递归赋值
一切准备就绪,就到了赋值阶段:
对于Map、Set都是差不多的,先new一个空的Set、Map,然后遍历赋值,Set就使用
add
方法,Map使用set
方法全部代码
铺垫代码
baseClone主逻辑:
The text was updated successfully, but these errors were encountered: