Vue-浅拷贝与深拷贝

1、释义

  • 浅拷贝:创建一个新对象,这个对象有着原始对象属性值的精确拷贝;如果是基础类型拷贝的就是基础类型的值,如果是引用类型拷贝的就是内存地址;如果其中一个对象改变了这个地址就会影响另一个对象
  • 深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新的对象,改变对象不会影响原对象

2、示例

浅拷贝

  • 基本类型
    基本数据类型是存储在栈内存中
var a = 1
var b = a
b = 2
console.log(a,b)
// 1 2

Vue-浅拷贝与深拷贝_第1张图片
改变不会使原始数据改变

  • 引用类型
var per = {
name:'1'
}
var per1 = per
per1.name = "2"
console.log(per,per1)
// {name: "2"} {name: "2"}

Vue-浅拷贝与深拷贝_第2张图片

此时per1赋值的是per的地址,per1的操作指向的是同一地址的对象per,改变会使原始数据per改变

深拷贝

var per = {
name:'1'
}
// 创建新对象
var per1 = {}
per1 = per
per1.name = '2'
console.log(per,per1)
// {name: "1"} {name: "2"}

Vue-浅拷贝与深拷贝_第3张图片
创建per1并赋值,将per的属性值单独进行赋值,此时per1指向的是新地址,改变属性值并不影响原数据

多级结构

我们先看下单级结构

let a = [1, 2, 3];
let b = [];
a.forEach(item => {
  b.push(item)
})
b[0] = 0
console.log(a, b)
// [1, 2, 3] [0, 2, 3]

这时一级拷贝是深拷贝

再改下代码变成多级结构

let a = [1, 2, 3, [4, 5]];
let b = [];
a.forEach(item => {
  b.push(item)
})
b[3][1] = 4
console.log(a, b)
// [1, 2, 3, [4, 4]] [1, 2, 3, [4, 4]]

修改二维数组的元素还是会影响原数组,这时一级拷贝是浅拷贝

3、拷贝方案

首先来看看有哪些系统方法可以实现拷贝功能:

  • slice()
    单级结构时深拷贝,多级结构浅拷贝
  • concat()
    单级结构时深拷贝,多级结构浅拷贝
  • Object.assign()
    单级结构时深拷贝,多级结构浅拷贝
  • JSON.stringify()、JSON.parse()
    单级多级均为深拷贝,但需要注意无法拷贝RegExp对象、function和symbol
  • deepClone递归:
function deepClone(obj: any) {
  function isObject(o: any) {
    return (typeof o === 'object' || typeof o === 'function') && o !== null;
  }
  if (!isObject(obj)) {
    throw new Error('非对象');
  }
  let isArray = Array.isArray(obj);
  let newObj = isArray ? [...obj] : { ...obj };
  Reflect.ownKeys(newObj).forEach(key => {
    newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key];
  });
  return newObj;
}

4、结论

类型 基础数据类型 引用数据类型
浅拷贝 改变不会使原始数据改变 改变会使原始数据改变
深拷贝 改变不会使原始数据改变 改变不会使原始数据改变

如有疑问或不足之处,欢迎交流指正

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