深拷贝和浅拷贝
值类型:number,string,boolean 引用类型:object
他们的赋值不同,值类型是在栈内存中直接赋值,而引用类型是在栈内存中将地址值赋给它,对象内容却存在堆内存中。
通过拷贝来实现 引用类型 的赋值.
浅拷贝Object.assign;
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
var b = Object.assign({},a)
Object.defineProperty(Object, 'assign', {
value: function(target, ...args) {
if (target == null) {
return new TypeError('Cannot convert undefined or null to object');
}
// 目标对象需要统一是引用数据类型,若不是会自动转换
const to = Object(target);
for (let i = 0; i < args.length; i++) {
// 每一个源对象
const nextSource = args[i];
if (nextSource !== null) {
// 使用for...in和hasOwnProperty双重判断,确保只拿到本身的属性、方法(不包含继承的)
for (const nextKey in nextSource) {
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
// 不可枚举
enumerable: false,
writable: true,
configurable: true,
})
深拷贝
way3:工具库 lodash中有clone,和CloneDeep
先引入第三方工具,在克隆
var a = {name:'A',score:[99,100]}
var b = _.deepclone(a)//赋值
way2: json 的序列化成字符串,在反序列化为对象,但需要注意,对象中有属性是funtion就不能被序列化为字符串,就不可以用这种方法。
var b = JSON.parse(JSON.stringify(a))
way1:深拷贝(递归,需要考虑 循环引用递归,需要判断层数,跳出循环)
const cloneDeep1 = (target, hash = new WeakMap()) => {
// 对于传入参数处理
if (typeof target !== 'object' || target === null) {
return target;
}
// 哈希表中存在直接返回
if (hash.has(target)) return hash.get(target);
const cloneTarget = Array.isArray(target) ? [] : {};
hash.set(target, cloneTarget);
// 针对Symbol属性
const symKeys = Object.getOwnPropertySymbols(target);
if (symKeys.length) {
symKeys.forEach(symKey => {
if (typeof target[symKey] === 'object' && target[symKey] !== null) {
cloneTarget[symKey] = cloneDeep1(target[symKey]);
} else {
cloneTarget[symKey] = target[symKey];
}
})
}
for (const i in target) {
if (Object.prototype.hasOwnProperty.call(target, i)) {
cloneTarget[i] =
typeof target[i] === 'object' && target[i] !== null
? cloneDeep1(target[i], hash)
: target[i];
}
}
return cloneTarget;
}