js深拷贝与浅拷贝

103 阅读3分钟

为什么出现

由于js对基本数据类型与引用数据类型的处理方式不同

深浅拷贝(复制)一般用于引用类型的复制,不用于基本类型的复制

关于js数据类型

一、 定义(深拷贝&&浅拷贝)

深拷贝,是指拷贝对象的具体内容

是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放对象,且修改新对象不会影响原对象

是创建一个全新的对象,有着原始对象属性值的拷贝。对于属性值就是基本类型,就拷贝基本数据类型的值,如果属性值是引用类型,拷贝的是内存地址

浅拷贝,复制对象时,仅复制对象的引用,不是复制对象本身

其中一个对象的值发生改变,会影响到另外一个对象

let a = { name: '张三', age: 18 }
let b = a
b.name = '李四'
console.log(a)  // {name: '李四1', age: 18}
console.log(b)  // {name: '李四1', age: 18}

浅拷贝实现方式

二、浅拷贝的实现方式

三、深拷贝的实现方式

1.使用JSON.parse(JSON.stringfy(obj)) 序列化和反序列化

2.使用Object.assign()

将一个或多个源对象的可枚举属性拷贝到目标对象,返回目标对象

let a = { name: '张三', age: 18 }
let aa = { test1: '学生', test2: '初中' }
let b = Object.assign({}, a, aa)
b.name = 'zhangsan'
console.log(a)  // {name: '张三', age: 18}
console.log(b)  // {name: 'zhangsan', age: 18,test1: '学生', test2: '初中'}

3.使用扩展运算符(...)

既具有深拷贝性质,也具有浅拷贝性质

对于拷贝对象的第一层,属于深拷贝;对于拷贝对象更深层次,属于浅拷贝

扩展运算符是ES6新引入的语法,可用于讲一个对象的所有可枚举属性拷贝到另外一个对象中

let a = {
  name: '张三',
  age: 18,
  test: {
   a: '大学生'
  }
}
let b = { ...a }
// 更改第一层数据,原对象数据不会改变,属于深拷贝
b.name = '李四'

// 更改第二层的数据,原对象数据也发生改变,属于浅拷贝
b.test.a = '研究生'

console.log(a)  // {name: '张三', age: 18, test: {a: '研究生'}}
console.log(b)  // {name: '李四', age: 18,  test: {a: '研究生'}}

4.使用Array.prototype.concat()

可将一个或多个数组或值合并成一个新数组。将一个对象作为参数传递给concat()方法时,会将该对象作为一个值添加到数组中,从而实现深拷贝

let a = { name: '张三', age: 18 }
let aa = { test1: '学生', test2: '初中' }
let b = [].concat(a)
console.log(b)  // [{name: '张三', age: 18},{test1: '学生', test2: '初中'}]

5.使用Array.prototype.slice()

可以用于提取数组中的一部分,并将其作为一个新数组返回。将一个对象作为参数传递给slice()方法时,它会将对象作为一个值添加到数组中,从而实现深拷贝

let a = { name: '张三', age: 18 }
let b = [a].slice()
console.log(a)  // {name: '张三', age: 18}
console.log(b)  // [{name: '张三', age: 18}]