JavaScript深拷贝和浅拷贝

对于原始数据类型,并没有深浅拷贝的区别,深浅拷贝都是对于引用数据类型而言,如果我们要赋值对象的所有属性都是引用类型可以用浅拷贝

 浅拷贝:只复制一层对象,当对象的属性是引用类型时,实质复制的是其引用,当引用值发生改变时,也会跟着改变
深拷贝:深拷贝是另外申请了一块内存,内容和原来一样,更改原对象,拷贝对象不会发生改变

1、 浅拷贝实现

 for in 遍历实现

    let shallCopy => obj=>{
      let rst={}
      for(let key in obj){
        //只复制本身的属性(非继承过来的属性)枚举属性
        if(obj.hasOwnProperty(key)){
          rst[key]=obj[key]
        }
      }
      return rst
    }

     let start ={
      name:'古力娜扎',
      age:'22',
      friend:{
        name:'邓超'
      }
    }
    let copyStart=shallCopy(start)
    copyStart.name="热巴"
    copyStart.friend.name='黄渤'
    // 拷贝的第一层层如果是引用类型,拷贝的其实是一个指针,所以拷贝对象改变会影响原对象
    console.log(start.name,opyStart.friend.name) //古力娜扎 黄渤
Object.assign(target,source) (适用于对象)

可以把 n 个源对象拷贝到目标对象中去(拷贝的是可枚举属性)

let start = {
  name: '古力娜扎',
  age: '22',
  friend: {
    name: '邓超'
  }
}
let returnedTarget = Object.assign({}, start)
 扩展运算符...
let start = { name: '刘亦菲' }
let newStart = { ...start }
newStart.name = '迪丽热巴'
console.log(start.name) // 刘亦菲
 slice(适用于数组)
let a = [1, 2, 3, 4]
let b = a.slice()
b[0] = 9
console.log(a) //[1,2,3,4]

3 、深拷贝实现

JSON.parse(JSON.string(obj))
let obj = {
  name: '小明',
  dog: ['小花', '旺财']
}

let obj1 = JSON.parse(JSON.stringify(obj))
obj1.name = '小华'
obj1.dog[0] = '小白'
console.log(obj) //  {name: "小明", dog: ['小花', '旺财']}
// 原数组并没有改变,说明实现了深拷贝

let richGirl = [
  {
    name: '开心',
    car: ['宝马', '奔驰', '保时捷'],
    deive: function() {},
    age: undefined
  }
]

let richBoy = JSON.parse(JSON.stringify(richGirl))
console.log(richBoy)
/*
      1. 当属性值为undefined或函数,则序列化的结果会把函数或 undefined丢失
      2. 对象中存在循环引用的情况也无法正确实现深拷贝
      3. Symbol,不能被JSON序列化
      4. RegExp、Error对象,JSON序列化的结果将只得到空对象
      5. 会丢失对象原型
    */
 递归实现深拷贝
let deepClone = obj => {
  let newObj = Array.isArray(obj) ? [] : {}
  if (obj && typeof obj === 'object') {
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (obj[key] && typeof obj[key] === 'object') {
          newObj[key] = deepClone(obj[key])
        } else {
          // 如果不是对象直接拷贝
          newObj[key] = obj[key]
        }
      }
    }
  }
  return newObj
}

let richGirl = {
  name: '开心',
  car: ['宝马', '奔驰', '保时捷'],
  deive: function() {},
  age: undefined
}

let richBoy = deepClone(richGirl)

richBoy.deive = '渣男开大G'
richBoy.name = '小明'
richBoy.car = ['哈罗单车', '膜拜']
richBoy.age = 20

console.log(richGirl)
console.log(richBoy)

4、 第三方库实现拷贝

//cloneDeep: 深拷贝  clone:浅拷贝,此例子介绍深拷贝
const _ = require('lodash') //全部引入
const cloneDeep = require('lodash/cloneDeep') //引入单个方法,用的方法少建议用这种方式引入
let obj = {
  name: '开心',
  car: ['宝马', '奔驰', '保时捷'],
  deive: function() {},
  age: undefined
}
const newObj = cloneDeep(obj)
newObj.name = '不开心'
newObj.car[0] = '自行车'
console.log(obj, newObj) // 原对象不会改变

你可能感兴趣的:(javascript,前端,vue.js)