一. JS的内存结构
js的原始类型和引用类型
原始类型的值都放在栈内存中,引用类型放在堆内存中。
二. Vue.js的对象列表
三. 浅拷贝
https://www.bilibili.com/video/BV1T54y1n7og?spm_id_from=333.999.0.0
浅拷贝只能拷贝原始类型。对于对象中的引用类型数据是直接赋值,无法拷贝。
vue 向数据库添加学生信息,如果push的是data里的student,则会造成一改全改的情况,因为都是指向同一个堆空间。 所以利用浅拷贝,用for (let i in obj){ } 封装一个copy函数,参数是原来的obj,return返回的是拷贝完的新对象,向push里传入这个新对象,就能实现各自有独立的堆空间。
四. 递归
定义: 自己调用自己。
五. 深度拷贝
深度拷贝关键在于,若是拷贝对象,那么判断一下若是对象,用递归调用来拷贝即可。
六. 利用json进行拷贝克隆
通过JSON的stringify(对象转字符串)和parse(字符串转对象)方法,对要拷贝的对象转成字符串再转成对象,就实现了拷贝。 无需循环、递归、判断。
值得注意的是,这种方式不能复制对象中的方法,JSON会忽略undefined 函数 和 null
浅拷贝:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝:在计算机中开辟一块新的内存地址用于存放复制的对象。
将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象
深拷贝和浅拷贝最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用。
浅拷贝实现方法:
- Object.assign
- Object.assign是一个浅拷贝,它只是在根属性(对象的第一层级)创建了一个新的对象,但是对于属性的值是仍是对象的话依然是浅拷贝
- 不会拷贝对象继承的属性
- 不可枚举的属性
- 可以拷贝Symbol类型
- 扩展运算符、slice、concat
- 和assgin一样只拷贝一层
深拷贝实现方法:
- 循环+递归
- 只能实现object、array的深拷贝
- for…in 无法获得 Symbol 类型的键,而 Reflect 可以获取
- JSON.stringify
- 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
- 无法拷贝不可枚举的属性, 无法拷贝对象的原型链
- 拷贝Date引用类型会变成字符串
- 拷贝RegExp引用类型会变成空对象
- 对象中含有NaN、 Infinity和 - Infinity, 则序列化的结果会变成null
- 无法拷贝对象的循环应用(即obj[key] = obj)
- lodash(第三方库)