项目初次接触:获取的数据赋值给变量,经过开关按钮切换后,数据变了,发现原来只是浅拷贝了。
深拷贝:也叫 值拷贝
浅拷贝: 也叫 引用拷贝
浅拷贝就只是复制对象的引用
原始类型 Undefined,Null,Boolean, Number,String 是存入堆中,直接引用
Object, Array则是存入栈中,只用一个指针来引用值,如果拷贝后的对象发生变化,原对象也会发生变化
对象数据存放在堆内存中,对象变量存放在栈内存中,对象变量通过引用数据的堆地址实现对象访问
js 中的深拷贝(值拷贝)
基本数据类型:String, Number, Boolean, Undefined, Null ,在赋值的过程中都是值拷贝
js 中的浅拷贝(引用拷贝)
js 中的对象数据类型: Object , Array, Function, Map, Set ,在赋值过程中都是引用拷贝
将浅拷贝转换成深拷贝
Array 的深拷贝
通过 slice 方法
slice() 方法操作数组时,不会对原数组有影响,会产出一个新的数组
slice() 方法选择从给定的start参数开始的元素,并在给定的end 参数处结束,但不包括。
通过 concat 方法
数组的 concat() 方法,能够连接两个数组,同样不会改变原来的数组。用一个空数组连接另一个数组,即可实现深拷贝
let arr1 = [1,2,3];
let arr 2 = [].concat(arr1)
通过 ES6语法中 解构 ...
ES6 语法中的结构 ... 经常在数组的深拷贝中用到
let arr1 = [0,1,2]
let arr2 = [...arr1]
通过Array.forn方法
Array.from() 方法能从一个类似数组或可迭代对象中返回一个新的数组实例。通过Array.from()方法能获取到一个数组的深拷贝
let arr1 = [1,2,3]
let arr2 = Array.from(arr1)
Object的浅拷贝
通过Object.assign()方法
Object.assign(target,...source)
let copyobj = Object.assign({}, sourceobj);
针对深拷贝问题,需要使用其他办法,因为Object.assign()只复制属性值
通过展开语法实现浅拷贝
let copyObj = {...target}
通过Object.create() 实现浅拷贝
let cloneObj = Object.create(
Object.getPrototypeof(target),
Object.getOwnPropertyDescriptors(target))
Object 深拷贝
通过JSON转换实现深拷贝
let copyObj = JSON.parse(JSON.stringify(target))
也会存在一些问题: 对某些数据不支持:
如Date类型会被转为字符串类型,
Undefined和RegExp类型丢失等问题。
无法拷贝存在循环引用的对象。
拷贝自身可枚举字符串属性,原型链丢失。
属性特性丢失。 性能较差。
手动实现深拷贝
function deepClone(target) { if (!(target instanceof Object) || 'isClone' in target) return target; let clone = null; if (target instanceof Date) clone = new target.constructor(); else if(Array.isArray(target)) clone = []; else clone = new target.constructor(); let keys = Reflect.ownKeys(target); for (let key of keys) { if (Object.prototype.hasOwnProperty.call(target, key)) { target['isClone'] = null; clone[key] = deepClone(target[key]); delete target['isClone']; } } return clone; }
方法二:项目中
export function deepClone(source) { if (!source && typeof source !== 'object') { throw new Error('error arguments', 'deepClone') } const targetObj = source.constructor === Array ? [] : {} Object.keys(source).forEach(keys => { if (source[keys] && typeof source[keys] === 'object') { targetObj[keys] = deepClone(source[keys]) } else { targetObj[keys] = source[keys] } }) return targetObj }
参考:https://juejin.cn/post/6872765382898221064#heading-8
标签:target,keys,前端,Object,source,let,遇见,拷贝 From: https://www.cnblogs.com/chuanmin/p/16603313.html