IT教程 ·

总结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.

    如图所示:

总结JavaScript工具的深浅拷贝 IT教程 第1张

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对象也收到影响,属于浅拷贝

总结JavaScript工具的深浅拷贝 IT教程 第2张

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

上面代码中,源对象obj1a属性的值是一个对象,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}

    如许就完成了深拷贝,以下图所示:

总结JavaScript工具的深浅拷贝 IT教程 第3张

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对象,完成深拷贝

总结JavaScript工具的深浅拷贝 IT教程 第4张

我们能够对深拷贝的代码举行封装优化

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年加工作经验的程序员,从大厂跳槽出来,遭遇了什么?

参与评论