【WEB前端-面试】深浅拷贝、赋值

栈stack & 堆heap

一般数据类型的数据存储————栈(存放的是基本类型的值和引用类型的地址)
引用类型的数据存储 ————堆(里面存放引用类型的值)

  • 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。

    • 如果属性是基本类型,拷贝的就是基本类型的值
    • 如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
  • 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

赋值和深浅拷贝的区别

  • 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此**,两个对象是联动的**。
  • 浅拷贝:重新在中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。引用类型你动,原来的也跟着动。
  • 深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。

图源:https://www.bilibili.com/video/BV1sN411974w?p=5

浅拷贝实现方式

浅拷贝只会对对象的各个属性进行复制,导致引用类型指向同一块内存地址。

实现方式:

  • Object.assign()
  • lodash 里面的 _.clone
  • …展开运算符
  • Array.prototype.concat
  • Array.prototype.slice
// 浅拷贝的函数封装
function shallowCopy(obj) {
  var dst = {};
  for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      dst[prop] = obj[prop];
    }
  }
  return dst;
}

Object.assign():

var obj = { a: {a: "kobe", b: 39} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "wade";
console.log(obj.a.a); // wade

Array.prototype.concat()

let arr = [1, 3, {
   username: 'kobe'
}];
let arr2=arr.concat();    
arr2[2].username = 'wade';
console.log(arr);

Array.prototype.slice()

let arr = [1, 3, {
   username: ' kobe'
}];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr);

Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。

深拷贝实现方式

实现方式:

  • JSON.parse(JSON.stringify())
  • 手写递归
  • cloneDeep
  • Jquery.extend()

1. JSON.parse(JSON.stringify())

原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
但不能处理函数

let arr = [1, 3, {
   username: ' kobe'
}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)

2. 手写递归方法

function deepClone(obj) {
  var cloneObj = new obj.constructor();
  if (obj === null) return obj;
  // a instanceof b: b的prototype是否在a的原型链上
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (typeof obj !== 'object') return obj;
  for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      cloneObj[prop] = deepClone(obj[prop]);
    }
  }
  return cloneObj;
}

3. 函数库lodash

var _ = require('lodash');
var obj1 = {
   a: 1,
   b: { f: { g: 1 } },
   c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false

参考:https://github.com/ljianshu/Blog/issues/5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值