js深拷贝与浅拷贝

首先简单介绍一下深拷贝与浅拷贝
如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力

浅拷贝就是只复制数组(对象)本身,而不复制其内容(引用类型的数据内容),最终两个数组中指向同一套数据。深拷贝则是既赋值本身也赋值内容。
Js中对于引用类型的数据,默认进行的都是浅拷贝。下面实现 **

对象与数组 分别实现 “浅层深拷贝” 与 “深层 deep深拷贝”

**

//-------------------------------- 数组深拷贝 ------------------------------------------
// 方法1 concat 可以实现 "浅"层深拷贝,当数组中存储的是对象 数组 等高级数据类型时无法实现深拷贝
// let tempAry=[{name:“小明”},2,[2]]
// let tempAry2=tempAry.concat()
// tempAry2[0].name=‘小B’
// tempAry2[1]=3
// tempAry2[2][0]=3
// console.log(tempAry2)
// console.log(tempAry)

// 方法2 splise 可以实现 "浅"层深拷贝,当数组中存储的是对象 数组 等高级数据类型时无法实现深拷贝
// let tempAry=[{name:“小明”},2,[2]]
// let tempAry2=tempAry.slice()
// tempAry2[0].name=‘小B’
// tempAry2[1]=3
// tempAry2[2][0]=3
// console.log(tempAry2)
// console.log(tempAry)

// 方法3 for循环 可以实现 "浅"层深拷贝,当数组中存储的是对象 数组 等高级数据类型时无法实现深拷贝
// let tempAry=[{name:“小明”},2,[2]]
// let tempAry2=[]
// for(let a=0 ;a<tempAry.length;a++){
// tempAry2.push(tempAry[a])
// }
// tempAry2[0].name=‘小B’
// tempAry2[1]=3
// tempAry2[2][0]=3;
// console.log(tempAry2)
// console.log(tempAry)

// 方法4 使用递归 可以实现"深层深拷贝"
let tempAry = [{ name: “小明” }, 2, [2]]
function _deepClone(source) {
let target;
//首先 判断是否为object类型 arrary也是object类型
if (typeof source === ‘object’) {
console.log(typeof source)
//接着 判断是数组还是对象
target = Array.isArray(source) ? [] : {}
//使用fo in 进行序列化
for (let key in source) {
//无继承属性的才进行copy
if (source.hasOwnProperty(key)) {
//判断属性中是否为Object 类型
//如果不是obj 则进行普通赋值
if (typeof source[key] !== ‘object’) {
target[key] = source[key]
}
//如果是Obj类型 则继续进行 递归 赋值对象
else {
target[key] = _deepClone(source[key])
}
}
}
} else {
target = source
}
return target
}
let tempAry2=_deepClone(tempAry)
tempAry2[0].name=‘小B’
tempAry2[1]=3
tempAry2[2][0]=3;
console.log(tempAry2)
console.log(tempAry)

// -----------------------------对象实现深拷贝-----------------------------
// function Test() {
// this.name = “xiaozheng”
// this.age = 15
// this.run = function () {
// console.log(“跑起来”)
// }
// this.obj={
// a:‘xiaoA’,
// b:“xiaoB”
// }
// }

// let obj1=new Test()
// // 方法1 使用先序列化为字符串对象 在反序列化回来 该方法可以实现 更深层拷贝,但是无法拷贝 方法
// let obj2=JSON.parse(JSON.stringify(obj1) )
// obj2.obj.a=‘xiaoC’

// obj2.name=‘1’
// console.log(obj2)
// console.log(obj1)
// 序列化对象无法对方法进行修改

// // 方法2 使用Object.assign()方法 可以实现 "浅层"深拷贝 针对深拷贝,需要使用其他办法,
// 因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那
// 个引用。也就是说,如果对象的属性值为简单类型(如string, number),通过Object.assign({},srcObj)
// ;得到的新对象为深拷贝;如果属性值为对象或其它引用类型,那对于这个对象而言其实是浅拷贝的。

// function Test() {
// this.name = “xiaozheng”
// this.age = 15
// this.run = function () {
// console.log(“跑起来”)
// }
// this.obj={
// a:‘xiaoA’,
// b:“xiaoB”
// }
// }
// let TestObj2=new Test()
// let obj5={}
// Object.assign(obj5,TestObj2)
// obj5.name=‘A’
// obj5.run=function(){
// console.log(“不想跑”)
// }
// obj5.obj.a=‘xiaoC’
// obj5.run()
// TestObj2.run()
// console.log(obj5)
// console.log(TestObj2)

// 方法3 使用 for in 赋值给新对象 实现深拷贝对象 该方法也是无法拷贝更深层的对象
// function Test() {
// this.name = “xiaozheng”
// this.age = 15
// this.run = function () {
// console.log(“跑起来”)
// }
// this.obj={
// a:“1”,
// b:‘2’
// }
// }

// let test1=new Test()
// let test2={}
// for(let key in test1){
// test2[key]=test1[key]
// }

// test2.name=‘xiaob’
// test2.obj.a=‘3’
// console.log(test2)
// console.log(test1)
// function Test2() {
// this.name = ‘xiaolv’
// this.age = 2
// this.sing = function () {
// console.log(“唱歌”)
// }
// }
// // Test2的显示原型指向 Test的原型对象
// Test2.prototype.proto = new Test
// var test2 = new Test2()

// //带继承关系的循环
// // for (let key in test2) {
// // console.log(key)
// // }
// //不带继承关系的循环
// let cloneObject={}
// for (let key in test2) {
// if (test2.hasOwnProperty(key)) {
// // console.log(“无继承”, key)
// cloneObject[key]=test2[key]
// }
// }
// cloneObject.name=‘小红’
// console.log(test2)
// console.log(cloneObject)

// 方法 4 使用递归

// function Test() {
// this.name = “xiaozheng”
// this.age = 15
// this.run = function () {
// console.log(“跑起来”)
// }
// this.obj = {
// a: “修改前”,
// b: ‘2’
// }
// }
// function _deepClone(source) {
// let target;
// //首先 判断是否为object类型 arrary也是object类型
// if (typeof source === ‘object’) {
// console.log(typeof source)
// //接着 判断是数组还是对象
// target = Array.isArray(source) ? [] : {}
// //使用fo in 进行序列化
// for (let key in source) {
// //无继承属性的才进行copy
// if (source.hasOwnProperty(key)) {
// //判断属性中是否为Object 类型
// //如果不是obj 则进行普通赋值
// if (typeof source[key] !== ‘object’) {
// target[key] = source[key]
// }
// //如果是Obj类型 则继续进行 递归 赋值对象
// else {
// target[key] = _deepClone(source[key])
// }
// }
// }
// } else {
// target = source
// }
// return target
// }

// let temp = new Test()

// let temp2 = _deepClone(temp)
// temp2.obj.a = ‘修改后’
// temp2.name = ‘b’
// console.log(temp2)
// console.log(temp)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值