javascript// 深拷贝函数,参数是一个待拷贝的对象
function deepClone(originValue) {
// 如果传入的是null或者不是对象类型, 那么直接返回
if(originValue == null || typeof originValue !== 'object') {
return originValue
}
// 创建一个新对象,递归拷贝属性
const newObj = {}
for(const key in originValue) {
// 不拷贝原型上的
if(originValue.hasOwnProterty(key)) {
newObj[key] = deepClone(originValue[key])
}
}
return newObj
}
测试代码
javascriptconst obj = {
name: 'zhangsan',
address: {
city: 'hangzhou'
}
}
const newObj = deepClone(obj)
obj.address.city = 'beijing'
console.log(newObj) // { name: 'zhangsan', address: { city: 'hangzhou' } }
可以看到 obj.address.city
改成了 beijing
但是 newObj.address.city
还是 hangzhou
。说明已经对属性是对象类型作了深拷贝
javascriptfunction deepClone(originValue) {
if(originValue == null || typeof originValue !== 'object') {
return originValue
}
// 判断传入的是数组还是对象
const newObj = Array.isArray(originValue) ? [] : {}
for(const key in originValue) {
// 不拷贝原型上的
if(originValue.hasOwnProterty(key)) {
newObj[key] = deepClone(originValue[key])
}
}
return newObj
}
测试代码
javascriptconst obj = {
name: 'zhangsan',
address: {
city: 'hangzhou'
},
friends: ['zhangsan', 'lisi']
}
const newObj = deepClone(obj)
obj.address.city = 'beijing'
obj.friends[0] = 'wangwu'
console.log(newObj)
// {
// name: 'zhangsan',
// address: { city: 'hangzhou' },
// friends: [ 'zhangsan', 'lisi' ]
//}
可以看到 obj.friends[0]
改成了 wangwu
但是 newObj.friends[0]
还是 zhangsan
。说明已经对属性是数组类型作了深拷贝
函数一般认为只使用来进行代码的复用,不需要进行深拷贝,但若实现一下会更好。
jsfunction deepClone(originValue) {
// 判断是否是函数类型
if (originValue instanceof Function) {
// 将函数转成字符串
let str = originValue.toString()
// 截取函数体内容字符串
let subStr = str.substring(str.indexOf("{") + 1, str.lastIndexOf("}"))
// 利用截取函数体内容的字符串和函数的构造器重新生成函数并返回
return new Function(subStr)
}
if(originValue == null || typeof originValue !== 'object') {
return originValue
}
// 判断传入的是数组还是对象
const newObj = Array.isArray(originValue) ? [] : {}
for(const key in originValue) {
// 不拷贝原型上的
if(originValue.hasOwnProterty(key)) {
newObj[key] = deepClone(originValue[key])
}
}
return newObj
}
测试
javascriptconst obj = {
foo: function () {
console.log("function");
},
};
const newObj = deepClone(obj);
console.log(obj.foo === newObj.foo); // false
javascriptfunction deepClone(originValue) {
// 判断是否是函数类型
if (originValue instanceof Function) {
// 将函数转成字符串
let str = originValue.toString()
// 截取函数体内容字符串
let subStr = str.substring(str.indexOf("{"), 1, str.lastIndexOf("}"))
// 利用截取函数体内容的字符串和函数的构造器重新生成函数并返回
return new Function(subStr)
}
// 判断是否是Date类型
if(originValue instanceof Date) {
return new Date(originValue.getTime())
}
// 判断是否是Set类型(浅拷贝)
if(originValue instanceof Set) {
return new Set([...originValue])
}
// 判断是否是Map类型(浅拷贝)
if(originValue instanceof Map) {
return new Map([...originValue])
}
if(originValue == null && typeof originValue !== 'object') {
return originValue
}
const newObj = Array.isArray(originValue) ? [] : {}
for(const key in originValue) {
// 不拷贝原型上的
if(originValue.hasOwnProterty(key)) {
newObj[key] = deepClone(originValue[key])
}
}
return newObj
}
测试
javascriptconst obj = {
name: 'zhangsan',
address: {
city: 'hangzhou'
},
friends: ['zhangsan', 'lisi'],
set: new Set([1,2,3]),
map: new Map([['aaa',111], ['bbb', '222']]),
createTime: new Date()
}
const newObj = deepClone(obj)
console.log(newObj.set === obj.set) // false
console.log(newObj.map === obj.map) // false
console.log(newObj.createTime === obj.createTime) // false
javascriptfunction deepClone(originValue) {
// 判断是否是函数类型
if (originValue instanceof Function) {
// 将函数转成字符串
let str = originValue.toString()
// 截取函数体内容字符串
let subStr = str.substring(str.indexOf("{"), 1, str.lastIndexOf("}"))
// 利用截取函数体内容的字符串和函数的构造器重新生成函数并返回
return new Function(subStr)
}
// 判断是否是Date类型
if(originValue instanceof Date) {
return new Date(originValue.getTime())
}
// 判断是否是Set类型(浅拷贝)
if(originValue instanceof Set) {
return new Set([...originValue])
}
// 判断是否是Map类型(浅拷贝)
if(originValue instanceof Map) {
return new Map([...originValue])
}
// 判断是否是Smybol类型
if(typeof originValue === 'symbol') {
return Symbol(originValue.description)
}
if(originValue == null && typeof originValue !== 'object') {
return originValue
}
const newObj = Array.isArray(originValue) ? [] : {}
for(const key in originValue) {
newObj[key] = deepClone(originValue[key])
}
// 对key是Symbol做处理
const symbolKeys = Object.getOwnPropertySymbols(originValue)
for(const key of symbolKeys) {
// 不拷贝原型上的
if(originValue.hasOwnProterty(key)) {
newObj[key] = deepClone(originValue[key])
}
}
return newObj
}
测试
javascriptconst s1 = Symbol('aaa')
const s2 = Symbol('bbb')
const obj = {
name: 'zhangsan',
address: {
city: 'hangzhou'
},
friends: ['zhangsan', 'lisi'],
set: new Set([1,2,3]),
map: new Map([['aaa',111], ['bbb', '222']]),
createTime: new Date(),
eating: function() {
console.log(this.name + ' is eating')
},
s1: s1,
[s2]: {a: 1}
}
const newObj = deepClone(obj)
console.log(obj.s1 === newObj.s1) // flase
console.log(obj[s2] === newObj[s2]) // false
javascript// 参数中设置一个WeakMap用来保存
function deepClone(originValue, map = new WeakMap()) {
// 判断是否是函数类型
if (originValue instanceof Function) {
// 将函数转成字符串
let str = originValue.toString()
// 截取函数体内容字符串
let subStr = str.substring(str.indexOf("{"), 1, str.lastIndexOf("}"))
// 利用截取函数体内容的字符串和函数的构造器重新生成函数并返回
return new Function(subStr)
}
// 判断是否是Date类型
if(originValue instanceof Date) {
return new Date(originValue.getTime())
}
// 判断是否是Set类型(浅拷贝)
if(originValue instanceof Set) {
return new Set([...originValue])
}
// 判断是否是Map类型(浅拷贝)
if(originValue instanceof Map) {
return new Map([...originValue])
}
// 判断是否是Smybol类型
if(typeof originValue === 'symbol') {
return Symbol(originValue.description)
}
if(originValue == null && typeof originValue !== 'object') {
return originValue
}
// 判断之前是否存过,如果有则直接获取返回
if(map.has(originValue)) {
return map.get(originValue)
}
const newObj = Array.isArray(originValue) ? [] : {}
// 创建的newObj放到map里
map.set(originValue, newObj)
for(const key in originValue) {
newObj[key] = deepClone(originValue[key], map)
}
// 对key是Symbol做处理
const symbolKeys = Object.getOwnPropertySymbols(originValue)
for(const key of symbolKeys) {
// 不拷贝原型上的
if(originValue.hasOwnProterty(key)) {
newObj[key] = deepClone(originValue[key], map)
}
}
return newObj
}
测试
javascriptconst s1 = Symbol('aaa')
const s2 = Symbol('bbb')
const obj = {
name: 'zhangsan',
address: {
city: 'hangzhou'
},
friends: ['zhangsan', 'lisi'],
set: new Set([1,2,3]),
map: new Map([['aaa',111], ['bbb', '222']]),
createTime: new Date(),
eating: function() {
console.log(this.name + ' is eating')
},
s1: s1,
[s2]: {a: 1}
}
obj.info= obj
const newObj = deepClone(obj)
console.log(newObj)
jsfunction deepClone(obj) {
return new Promise((resolve) => {
const { port1, port2 } = new MessageChannel();
port1.postMessage(obj);
port2.onmessage = (msg) => {
resolve(msg.data);
};
});
}
const obj = {
a: { b: 1 },
};
deepClone(obj).then((res) => {
console.log({ res: res, obj });
obj.a.b = 2;
console.log({ res: res, obj });
});
本文作者:叶继伟
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!