clone是js中老生常谈的问题了,just这个库,实现了一个简易版的克隆。
根据我在真实场景下的经验,一般的深克隆也大多都是考虑到数组和对象就行了,并且像循环引用这种根本不会出现,所以我觉得在一般场景下是够用的了。
然后也确实想去通过观看别人优秀的代码,理解并自己能够写出来,来提升自己。
当然我们这里说的都是深克隆
function clone(obj) {
const valueType = Object.prototype.toString.call(obj).slice(8, -1)
// 这个赋值是为了克隆基础类型数据
let result = obj
// 克隆Set
if (valueType === 'Set') {
return new Set([...obj].map(value => clone(value)))
}
// 克隆Map
if (valueType === 'Map') {
return new Map([...obj].map(([k, v]) => [clone(k), clone(v)]))
}
// 克隆Date
if (valueType === 'Date') {
return new Date(obj.getTime())
}
// 克隆RegExp
if (valueType === 'RegExp') {
return new RegExp(obj.source, getRegFlags(obj))
}
// 克隆数组或者对象
if (valueType === 'Array' || valueType === 'Object') {
result = Array.isArray(obj) ? [] : {}
for (let k in obj) {
result[k] = clone(obj[k])
}
}
return result
}
function getRegFlags(reg) {
if (reg.flags) {
return reg.flags
}
const flags = []
reg.indices && flags.push('d')
reg.global && flags.push('g')
reg.ignoreCase && flags.push('i')
reg.multiline && flags.push('m')
reg.dotAll && flags.push('s')
reg.unicode && flags.push('u')
reg.unicodeSets && flags('v')
reg.sticky && flags.push('y')
return flags.join('')
}
主要的思路就是通过Object原型上的toString方法,获取到当前值的类型,根据不同类型去做不同的处理 如果不是引用类型,那就直接返回