美文网首页
js 对象深拷贝与浅拷贝

js 对象深拷贝与浅拷贝

作者: igor_d140 | 来源:发表于2018-09-22 17:48 被阅读25次

    js基本数据类型与对象指针(引用地址)存放在栈内存,对象实际存放在堆内存
    变量标志符和值(基本数据和指针)保存在栈内存
    链接:关于JS堆栈与拷贝(基本数据类型新增symbol)
    链接:react渲染效率--深复制 immutable
    链接:React 的性能优化(一)当PureComponent 遇上ImmutableJS

    对象赋值、浅拷贝与深拷贝
    浅拷贝(存在关联)与深拷贝(不存在关联)的区别是克隆对象与原始对象是否存在关联

    类型 实质 表现 方法
    浅拷贝赋值 指针(引用地址)相等,指向同一对象和内存空间(克隆对象即原始对象) 克隆对象属性值变化原始对象跟着变化 赋值var a = b = { a: 1 }(a == b)
    浅拷贝不完全深拷贝 引用地址不相等,对象部分数据重新开辟新空间 克隆对象部分属性值变化原始对象跟着变化 Object.assign(target, ...source)
    深拷贝 引用地址完全不同,数据存在于重新开辟的新空间 克隆对象与原始对象无关联

    浅拷贝

    var obj = {
      a: 1,
      b: 2,
      c: [1, 2, 3]
    }
    var cloneObj = {}
    Object.assign(cloneObj, obj)
    // var cloneObj = Object.assign({}, obj)     // ES6
    // var cloneObj = {...obj}                            //ES7
    
    cloneObj.c[0] = 101
    console.log(obj.c[0])    //101
    
    cloneObj.a = 10
    console.log(obj.a)    // 1
    
    

    深拷贝

    • 方法一 递归
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>test</title>
    </head>
    <body>
      <button></button>
      <button></button>
      <button></button>
      <button></button>
      <button></button>
      <button></button>
      <script>
        const nodes = document.getElementsByTagName('button')
        const element = document.createElement('button')
        const eles = cloneDeep(element)
        const eless = [eles, eles, eles, eles]
        const tips = () => {
          console.log(1)
        }
        function Person(name, age) {
          return {
            name: name,
            age: age
          }
        }
        var obj = {
          a: 2,
          isEnble: true,
          c: () => {
            console.log('fn')
          },
          Person: Person,
          dom: nodes,
          element: element,
          eles: eles,
          eless: eless,
          d: tips,
          yy: new Date(),
          b: {
            b: 3,
            c: {
              c: 8,
              d: {
                d:9,
                e: {
                  e:10,
                  f: [1,2 ,3, 4]
                }
              }
            }
          }
        }
        // JSON.parse(JSON.stringify(new Date))
        // "2018-09-21T15:47:40.671Z"
        
        // Object.prototype.toString.call(params)
        // "[object Date]"
        // "[object Array]"
        // "[object Object]"
        // "[object Function]"
        // "[object Symbol]"
        // "[object Null]"
        // "[object Undefined]"
        // "[object Number]"
        // "[object Boolean]"
        // "[object String]"
        // "[object HTMLCollection]"
    
        function isObject(value) {
          var type = Object.prototype.toString.call(value)
          return value !== null && type === '[object Object]' || type === '[object Arrary]' 
        }
        const isArray = Array.isArray
        function baseclone(value){
          var __obj = {}
          for(let key in value){
            let attr = value[key]
            if(!isObject(attr)){
              __obj[key] = attr
            }else{
              if(isArray(attr))
                __obj[key] = Array.prototype.slice.call(attr, 0)
              else
                __obj[key] = baseclone(attr)
            }
          }
          return __obj
        }
        function cloneDeep(value) {
          if(!isObject(value)){
            return value
          }else{
            if(isArray(value))
              return Array.prototype.slice.call(value, 0)
            else
              return baseclone(value)
          }
        }
        
      </script>
    </body>
    </html>
    
    • 方法二 序列化
      有缺陷:数据有函数,日期,DOM节点等不适用
    var obj = ....    //同上
    var c = JSON.parse(JSON.stringify(obj))
    

    相关文章

      网友评论

          本文标题:js 对象深拷贝与浅拷贝

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