js 深浅拷贝

132 阅读3分钟

深拷贝、浅拷贝、赋值、数据类型、instanceof、typeof

  • js的一般数据类型存储和引用类型的数据存储

数据类型

  • 基本类型:string、boolean、number、null、undefined、symbol

      typeof null —— object,其它都可以显示各自类型
    
  • 引用类型:对象、数组、方法、Date、RegExp

      typeof function —— function,其它 object
    
  • instanceof

    instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

          object instanceof constructor
          object:某个实例对象     constructor:某个构造函数
          用来检测  constructor.prototype 是否存在于参数  object 的原型链上。
    

浅拷贝与深拷贝的区别

  • 浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝;如果属性是基本类型,拷贝的就是基本类型的值;如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了地址,就会影响到另一个

  • 深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

  • var obj = {} obj在栈里,{}在堆里

浅拷贝与赋值的区别

  • 当我们把一个对象赋值给一个新的变量时,赋的其实时该对象在栈中的地址,而不是堆中的数据,也就是两个对象指向的时同一个存储空间,无论哪个发生改变,其实都是改变的存储空间的内容,因此两个对象是联动的(对象的所有类型都影响)

  • 浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响(浅拷贝的对象指向一个新的地址)(基本类型不影响,引用类型影响)

  • 深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响(所有类型都不影响)

    • 例子

      var person = {
      	name: 'xxx',
      	hobby: ['1', '2', '3']
      }
      var person1 = person
      person1.name = 'yyy'
      person1.hobby[0] = '11'
      console.log(person)
      console.log(person1) // 结果是一样的,都是修改过后的对象
      // 这是赋值
      
      function shallowCopy(obj){
      	var target = {}
      	far(var i in obj) {
      		if(obj.hasOwnProperty(i)) {
      				target[i] = obj[i]
      		}
      	}
      	return target
      }
      var person1 = shalloCopy(person)
      person1.name = 'yyy'
      person1.hobby[0] = '11'
      console.log(person)
      console.log(person1) // 结果不一样,基本类型不一样,引用类型一样
      

浅拷贝的实现:

  • Object.assign():var newObj = Object.assign({}, originObj)

  • lodash里面的_.clone

  • ...展开运算符

  • Array.prototype.concat

  • Array.prototypo.slice

  • 自行实现

      function shallowCopy(obj){
      	var target = {}
      	far(var i in obj) {
      		if(obj.hasOwnProperty(i)) {
      				target[i] = obj[i]
      		}
      	}
      	return target
      }
    

深拷贝的实现:

  • JSON.parse(JSON.stringify())

    弊端:无法拷贝Date、RegExp、function类型

  • 递归的操作

      function deepClone(obj) {
      	var cloneObj = {}
      	if (obj === null) return obj
      	if (obj instanceof Date) return new Date(obj)
      	if (obj instanceof RegExp) return new RegExp(obj)
      	if (typeof obj !== 'object') return obj // 基本类型
      	far(var i in obj) {
      		if(obj.hasOwnProperty(i)) {
      				target[i] = deepClone(obj[i])
      		}
      	}
      }
    
  • Jquery.extend()

  • lodash里面的_.baseClone