美文网首页
理解js中的浅拷贝和深拷贝

理解js中的浅拷贝和深拷贝

作者: 不懂代码的小白 | 来源:发表于2019-09-25 14:08 被阅读0次
    JavaScript的变量类型
    • Number Boolean String Null undefined Object Function
    基本类型
    • Number Boolean String undefined null
    • 变量是直接按值存放的,存放在栈内存中的简单数据段,可以直接访问。
    引用类型
    • Object Function
    • 存放在堆内存中的对象,变量保存的是一个指针,这个指针指向另一个位置。当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

    浅拷贝

    • 复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变。

    深拷贝

    • 重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型。两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。

    浅拷贝和深拷贝的区别

    • 浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用。
    • 深拷贝是拷贝多层,递归复制了所有层级。

    浅拷贝实现

    Object.assign()
    • 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
    let obj1 = {
      name: '张三',
      age: 18,
      child: {
        name: '李四',
        age: 22
      }
    }
    let obj2 = Object.assign({}, obj1)
    obj2.age = 50
    obj2.child.age = 888
    console.log(obj1)
    console.log(obj2)
    
    $ node index.js
    { name: '张三', age: 18, child: { name: '李四', age: 888 } }
    { name: '张三', age: 50, child: { name: '李四', age: 888 } }
    
    自定义方法 shadowCopy()
    • 实现简单的引用复制
    function shadowCopy(obj) {
     let newObj = {}
     for (let k in obj) {
       newObj[k] = obj[k]
     }
     return newObj
    }
    let obj1 = {
     name: '张三',
     age: 18,
     child: {
       name: '李四',
       age: 22
     }
    }
    let obj2 = shadowCopy(obj1)
    obj2.age = 50
    obj2.child.age = 888
    console.log(obj1)
    console.log(obj2)
    
    $ node index.js
    { name: '张三', age: 18, child: { name: '李四', age: 888 } }
    { name: '张三', age: 50, child: { name: '李四', age: 888 } }
    

    深拷贝实现

    JSON.paerse() JSON.stringify()
    • 用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。
    缺点
    • 会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。

    • 能正确处理的对象只有 Number String Boolean Array 扁平对象,即那些能够被 json 直接表示的数据结构。

    • RegExp对象是无法通过这种方式深拷贝。

    • 只有可以转成JSON格式的对象才可以这样用,function没办法转成JSON。复制后生成的对象的function属性会直接消失,这个方法只能用在单纯只有数据的对象。

    let obj1 = {
      name: '张三',
      age: 18,
      child: {
        name: '李四',
        age: 22
      },
      func() {
        console.log('hello:' + this.name)
      }
    }
    let obj2 = JSON.parse(JSON.stringify(obj1))
    obj2.age = 50
    obj2.child.age = 888
    console.log(obj1)
    console.log(obj1.func)
    console.log('------------------------')
    console.log(obj2)
    console.log(obj2.func)
    
    $ node index.js
    { name: '张三',
      age: 18,
      child: { name: '李四', age: 22 },
      func: [Function: func] }
    [Function: func]
    ------------------------
    { name: '张三', age: 50, child: { name: '李四', age: 888 } }
    undefined
    
    自定义方法 deepCopy()
    function deepCopy(obj) {
      let result = Array.isArray(obj) ? [] : {};
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (typeof obj[key] === 'object' && obj[key]!==null) {
            result[key] = deepCopy(obj[key]);   //递归复制
          } else {
            result[key] = obj[key];
          }
        }
      }
      return result;
    }
    let obj1 = {
      name: '张三',
      age: 18,
      child: {
        name: '李四',
        age: 22
      },
      func() {
        console.log('hello:' + this.name)
      }
    }
    let obj2 = deepCopy(obj1)
    obj2.name = '陈二'
    obj2.age = 50
    obj2.child.name = 'bgbhjbj'
    obj2.child.age = 888
    console.log(obj1)
    console.log(obj1.func)
    console.log('------------------------')
    console.log(obj2)
    console.log(obj2.func)
    
    $ node index.js
    { name: '张三',
      age: 18,
      child: { name: '李四', age: 22 },
      func: [Function: func] }
    [Function: func]
    ------------------------
    { name: '陈二',
      age: 50,
      child: { name: 'bgbhjbj', age: 888 },
      func: [Function: func] }
    [Function: func]
    

    相关文章

      网友评论

          本文标题:理解js中的浅拷贝和深拷贝

          本文链接:https://www.haomeiwen.com/subject/tdpiuctx.html