js变量复制,复杂类型存的是地址值,浅拷贝只是把地址值复制了一份,拷贝对象和原对象指向同一个地址, 一个改变也会影响另外一个
浅拷贝
- 对象复制
- Object.assign()
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2); // 返回 {a:1, b:2, c:3}
target // {a:1, b:2, c:3}
- ...obg 扩展运算符
深拷贝
- JSON,parse(JSON.stringify)
- 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
- 无法拷贝不可枚举的属性,无法拷贝对象的原型链
- 拷贝Date引用类型会变成字符串
// let date = new Date()
// undefined
// DataTransfer
// ƒ DataTransfer() { [native code] }
// date
// Mon Dec 07 2020 10:48:10 GMT+0800 (中国标准时间)
// JSON.stringify(new Date())
// ""2020-12-07T02:48:58.265Z""
- 拷贝RegExp引用类型会变成空对象
- 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
- 无法拷贝对象的循环应用(即obj[key] = obj)
深拷贝实现
var obj = {
a: 2,
b: [1,2,3,{aa: 11, bb:22}],
c: function () {
console.log("cccc")
},
d: undefined,
e: 'e',
f: /^\d+$/
}
// let obj1 = JSON.parse(JSON.stringify(obj)) // 会丢失c的function 和d的undefined 正则({})/日期格式 会改变
// 方法1
function deepClone (obj) {
let objClone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) { // 如果是私有属性 不是原型上的才进入
if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
deepClone(obj[key])
} else {
objClone[key] = obj[key]
}
}
}
return objClone
}
let obj2 = deepClone(obj)
console.log(obj2)
// 方法2
function deepClone2 (obj) {
//过滤特殊情况
if (obj === null) return;
if (typeof obj != 'object') return obj;
if (obj instanceof RegExp) {
return new RegExp(obj)
}
// => 不直接创建空对象的目的,克隆的结果和之前保持相同的所属类
let newObj = new obj.constructor;
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = deepClone2(obj[key])
}
}
return newObj;
}
let obj3 = deepClone2(obj);
console.log(obj3)
网友评论