总结JavaScript工具的深浅拷贝
Java基础——多线程
十四、对象的浅拷贝与深拷贝
- 什么是对象的拷贝?
将一个对象赋值给别的一个对象, 我们称之为对象的拷贝 - 什么是深拷贝, 什么是浅拷贝?
我们假定将A对象赋值给B对象 - 浅拷贝是指, 修正B对象的属性和要领会影响到A对象的属性和要领, 我们称之为浅拷贝
以下两种状况都属于浅拷贝:
1、默许状况下对象之间的直接赋值都是浅拷贝
let A = { name: 'zyx', age: 20 } let B = A console.log(B) // {name: "zyx", age: 20} //修正B的 name 属性 B.name = 'ls' //A 也收到影响 console.log(A) // {name: "ls", age: 20} console.log(B) // {name: "ls", age: 20}
赋值操纵(包括对象作为参数、返回值),不会拓荒新的内存空间,他只是赋值了对象的援用.也就是除了B这个名字以外,没有其他的内存开支,修正了A也就影响了B,修正了B,也就影响了A.
如图所示:
2、假如对象的属性包括了援用数据范例(数组、对象),那末哪怕不是直接赋值操纵,而是拓荒了一层新的内存空间,也就是说只拷贝了A对象的一层,这依然属于浅拷贝。
let A = {
name: 'ls',
age: 20,
hobbies: ['dance','basketball','read'],
dogs:{
name: '大黄',
color: 'yellow'
}
}
let B = {}
//定义一个函数,把A对象的属性复制一份给B
function extend(obj1,obj2){
for(var key in obj1){
obj2[key] = obj1[key]
}
}
extend(A,B)
//修正B对象中的援用范例数据 ,A对象也收到影响
B.dogs.color = 'red'
B.hobbies[0] = 'sing'
console.log(B)
console.log(A)
运转截图以下:修正B对象中的援用范例数据 ,A对象也收到影响,属于浅拷贝
3、ES6中新增的 Object.assign() 也是对象的浅拷贝
Object.assign
要领用于对象的兼并,将源对象(source)的一切可罗列属性,复制到目的对象(target)。 Object.assign
要领的第一个参数是目的对象,背面的参数都是源对象。 注重,假如目的对象与源对象有同名属性,或多个源对象有同名属性,则背面的属性会掩盖前面的属性。
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
上面代码中,源对象obj1
的a
属性的值是一个对象,Object.assign
拷贝获得的是这个对象的援用。这个对象的任何变化,都邑反应到目的对象上面。
4、扩大运算符(...)
应用扩大运算符能够在组织字面量对象时,举行克隆或许属性拷贝 ,属于浅拷贝
var obj = {a:1,b:{c:1}}
var obj2 = {...obj};
obj.a=2;
console.log(obj); //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}
obj.b.c = 2;
console.log(obj); //{a:2,b:{c:2}}
console.log(obj2); //{a:1,b:{c:2}}
5、Array.prototype.slice()
slice() 要领返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决议的原数组的浅拷贝。原始数组不会被转变。
- 深拷贝是指, 修正B对象的属性和要领不会影响到A对象的属性和要领, 我们称之为深拷贝
以下两种状况都属于深拷贝:
1、默许状况下一个对象的属性假如是基础数据范例, 那末举行复制(拷贝),都是深拷贝
假如A对象的属性都是基础数据范例(Number、String等),此时要想深拷贝一份A给B,该怎么做呢,在这类要拷贝的对象A只要基础范例的数据时,只需要在内存中拓荒一块空间存储B就好了。
let A = { name: 'zyx', age: 20 } let B = {} //定义一个函数,把A对象的属性复制一份给B function extend(obj1,obj2){ for(var key in obj1){ obj2[key] = obj1[key] } } extend(A,B) console.log(B) // {name: "zyx", age: 20} B.name = 'ls' console.log(B) // {name: "ls", age: 20} console.log(A) // {name: "zyx", age: 20}
如许就完成了深拷贝,以下图所示:
2、假如要拷贝的对象自身又包括了援用数据范例,即对象又包括数组或许对象,层层嵌套的状况下,想要完成对象的深拷贝,能够采纳递归的体式格局举行深拷贝。
let A = {
name: 'ls',
age: 20,
hobbies: ['dance','basketball','read'],
dogs:{
name: '大黄',
color: 'yellow'
}
}
let B = {}
//定义一个函数,把A对象的属性复制一份给B
function extend(obj1,obj2){
for(var key in obj1){
var item = obj1[key]
if(item instanceof Array){
obj2[key] = []
extend(item,obj2[key])
}else if(item instanceof Object){
obj2[key] = {}
extend(item,obj2[key])
}else{
obj2[key] = item
}
}
}
extend(A,B)
B.dogs.color = 'red'
B.hobbies[0] = 'sing'
console.log(B)
console.log(A)
运转发明,修正B对象的援用数据范例,不会影响到A对象,完成深拷贝
我们能够对深拷贝的代码举行封装优化
function deepClone(obj){
let cloneObj = {}
for(let key in obj){
if(typeof obj[key] === 'object'){
cloneObj[key] = deepClone(obj[key])
}else{
cloneObj[key] = obj[key]
}
}
return cloneObj
}
3、经由历程JSON.stringify完成深拷贝
JSON.stringify()是现在前端开发历程中最经常使用的深拷贝体式格局,道理是把一个对象序列化成为一个JSON字符串,将对象的内容转换成字符串的情势再保存在磁盘上,再用JSON.parse()反序列化将JSON字符串变成一个新的对象。
var obj1 = {
a:1,
b:[1,2,3]
}
var str = JSON.stringify(obj1)
var obj2 = JSON.parse(str)
console.log(obj2); //{a:1,b:[1,2,3]}
obj1.a=2
obj1.b.push(4);
console.log(obj1); //{a:2,b:[1,2,3,4]}
console.log(obj2); //{a:1,b:[1,2,3]}
7年加工作经验的程序员,从大厂跳槽出来,遭遇了什么?