js 对象深拷贝与浅拷贝

2018-09-22  本文已影响25人  igor_d140

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>
var obj = ....    //同上
var c = JSON.parse(JSON.stringify(obj))
上一篇下一篇

猜你喜欢

热点阅读