拷贝有个大前提,是针对对象的操作,当想复制一个对象的时候,才存在浅拷贝和深拷贝之分。浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。
浅拷贝实现方式 (浅拷贝的意思就是只复制引用,而未复制真正的值)
1.Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。 可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
2. ...展开运算符
let obj1 = {name:"Kobe",address:{x:100,y:100}}
let obj2 = {...obj1}
obj1.address.x=200;
obj1.name="wade";
console.log(obj2) //{name:"Kobe",address:{x:200,y:100}}
// ... 实现的是对象第一层的深拷贝,后面的只是拷贝的引用值
3. concat() 该方法可以连接两个或者更多的数组, 但是它不会修改已存在的数组,而是返回一个新数组
let arr = [1,3,{
username:"Kobe"
}];
let arr2 = arr.concat();
arr2[2].username = 'wade';
console.log(arr);
// [1,3,{ username:"wade"};
4. slice() 该方法不传值将会截取整个字段 slice只是对数组的第一层进行深拷贝
let arr = [1,3,{
username:'kobe'
}];
let arr2 = arr.slice();
arr2[2].username = 'wade';
console.log(arr) // [1,3,{username:'wade'}]
数组有两个方法 concat
和 slice
是可以实现对原数组的拷贝的,这两个方法都不会修改原数组,而是返回一个修改后的新数组。
深拷贝实现方式(深拷贝就是对目标的完全拷贝,不像浅拷贝那样只是复制了一层引用,就连值也都复制了)
1. JSON.parse(JSON.stringify())
JSON.stringify
是将一个 JavaScript
值转成一个 JSON
字符串。
JSON.parse
是将一个 JSON
字符串转成一个 JavaScript
值或对象。
可以处理数组和对象的深拷贝,但是不能处理函数和正则,因为这两者基于这两个函数处理后得到的结果不再是正则/函数
缺点:
1.会忽略undefined
2.会忽略symbol
3.不能序列化函数
4.不能解决循环引用的对象
2.如果所拷贝的对象含有内置对象,但是不包含函数,可以使用`messagechannel`,可以拷贝undefined和循环引用的对象
function structuralClone(obj) {
return new Promise(resolve => {
const { port1, port2 } = new MessageChannel()
port2.onmessage = ev => resolve(ev.data)
port1.postMessage(obj)
})
}
var obj = {
a: 1,
b: {
c: 2
}
}
obj.b.d = obj.b
// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
const test = async () => {
const clone = await structuralClone(obj)
console.log(clone)
}
test()
3.递归 (递归的思想就很简单了,就是对每一层的数据都实现一次 创建对象->对象赋值
的操作)
function deepClone(source){
const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
for(let keys in source){ // 遍历目标
if(source.hasOwnProperty(keys)){
if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
}else{ // 如果不是,就直接赋值
targetObj[keys] = source[keys];
}
}
}
return targetObj;
}
//演示
const originObj = { name:'axuebin',
sayHello:function(){
console.log('Hello World');
}
}
console.log(originObj); // {name: "axuebin", sayHello: ƒ}
const cloneObj = deepClone(originObj);
console.log(cloneObj); // {name: "axuebin", sayHello: ƒ}
总结:
1. 赋值运算符 = 实现的是浅拷贝,只拷贝对象的引用值;
2. Javascript中数组和对象自带的拷贝方法都是"首层浅拷贝";
3. JSON.stringify() 实现的是深拷贝,但是对目标对象有要求
4. 若想真正意义上的深拷贝还是递归。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!