深浅拷贝方法

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

1. 如果是基本数据类型,名字和值都会储存在栈内存中(不存在深浅拷贝,可以理解为值拷贝)

var a = 1;
b = a; // 栈内存会开辟一个新的内存空间,此时b和a都是相互独立的
b = 2;
console.log(a); // 1

2. 如果是引用数据类型,名字存在栈内存中,存在堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值

浅拷贝:从字面上的意思理解,是指比较浅的拷贝,它与原来的变量仍然指向同一个地址,两者之间相互影响,即其中一个改变会影响另一个的改变。浅拷贝也被称为引用拷贝,引用的意思就是取了个别名,例如张三是大名,狗蛋是他的引用,即为小名,张三变了,狗蛋自然也变了,因为他们本质上就是指同一个人

 当b=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值

 而当我们a[0]=1时进行数组修改时,由于a与b指向的是同一个地址,所以自然b也受了影响,这就是所谓的浅拷贝了。

 js中的对象数据类型:Object Array Function Map Set,在赋值过程中都是引用拷贝

let obj = {
     name: '静如秋叶',
     age: 3,
     height: 100
 }
 let obj2 = obj
 obj2.name = '小花'
 console.log(obj)    // {name: '小花‘, age: 3, height: 100}
 console.log(obj2)   // {name: '小花‘, age: 3, height: 100}

 深拷贝:从字面上的意思理解,是指很深的拷贝,到底有多深呢?深到不仅拷贝值,而且还独立开辟了一个空间。我的理解是:拷贝的过程中,独立地开辟了一个空间,这个对象指向这个地址,与原来的对象互不干扰。深拷贝也被称为值拷贝。

Array的深拷贝

(1) 通过slice方法

slice()操作数组时,不会对原数组有影响,会产出一个新的数组。

 let arr1 = [1, 42, 5, 6]
 let arr2 = arr1.slice()
 arr2[0] = 100
 console.log(arr1) // [1, 42, 5, 6]
 console.log(arr2) // [100, 42, 5, 6]

 (2)使用扩展运算符实现深拷贝

let arr5 = [0, 0, 1]
let arr6 = [...arr5]
arr5[0] = 10000
console.log(arr5) // [10000, 0, 1]
console.log(arr6) // [0, 0, 1]

 (3) 通过Array.from方法

Array.from()方法能从一个类似数组或可迭代对象中返回一个新的数组实例。通过Array.from()方法能获取到一个数组的深拷贝。

let arr7 = [1, 2, 3]
let arr8 = Array.from(arr7)
arr7[1] = 1000
console.log(arr7) // [1, 1000, 3]
console.log(arr8) // [1, 2, 3]

(4)通过concat方法

数组的concat()方法,能够连接两个数组,同样不会改变原来的数组。用一个空数组连接另一个数组,即可实现深拷贝

let arr3 = ['cat', 'dog', 'pig']
let arr4 = [].concat(arr3)
arr3[2] = 'big pig'
console.log(arr3) // ['cat', 'dog', 'big pig']
console.log(arr4) // ['cat', 'dog', 'pig']

Object的深拷贝 

(1)通过Object.assign()方法

ES6的Object.assign() Object.assign(target, …sources)用于对象的合并,将源对象中的所有可枚举属性,复制到目标对象中,并返回合并后的目标对象。后来的源对象的属性值,将会覆盖它之前的对象的属性。

 let person = {
     name: 'xia',
     age: 25,
     height: 160
 }
 let otherPerson = Object.assign({}, person)
 person.age = 30

 console.log(person)
 console.log(otherPerson)

(2)手动实现深拷贝

 

let obj1 = {
   a: 1,
   b: 2
}
let obj2 = {
   a: obj1.a,
   b: obj1.b
}
obj2.a = 3;
alert(obj1.a); // 1
alert(obj2.a); // 3

 (3)直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

万能转换器(对Array和Object等都适用) 

万能转换器 JSON.parse(JSON.stringify(obj))深拷贝已有对象,它可以深拷贝多层级的,不用担心嵌套问题。

  • JSON.stringfy() 将对象序列化成json对象
  • JSON.parse() 反序列化——将json对象反序列化成js对象

 

 let jack = {
     name: 'jack'
 }
 console.log(jack)
 console.log(JSON.stringify(jack))


 let obj = {
     name: '静茹秋叶'
 }
 console.log('obj: ', obj)
 console.log('json string: ', JSON.stringify(obj))

 let str = JSON.stringify(obj)
 console.log('--------------')
 console.log(str)
 console.log('str to obj: ', JSON.parse(str))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值