javascript对象拷贝
javascript克隆一个对象时,为什么改变复制过来的变量,为何被克隆对象的值也随之改变?
答案其实很简单,这是因为javascript对象的变量实际上只是一个指针,它指向内存中的对象存储位置。
当我们仅仅通过 var a = b // b为被拷贝对象 的方式去拷贝对象时,只能拷贝该对象的指针,相当于有两个指针指向内存中同一个位置。
什么是浅拷贝?
只遍历对象的第一层属性和值。当如果拷贝的值也为对象时,实际上只拷贝了这个值的指针,这个指针仍然指向原对象。
有哪些方式?
- object.asign({}, target);
- for in 一层遍历对象的属性和值
- Object.keys() 遍历属性
- object.entries() 遍历属性
- object.getOwnPropertyNames() 遍历属性
如何深拷贝对象?
- 可以采用序列化对象再反序列化回来。 这样做的弊端是,一些不可序列化的类型如日期类型,JSON.parse只会把它们当成字符串,而不是日期类型。
JSON.stringfy 不可转换的js属性
- undefined // 无
- function // 无
- regExp(转换后变成了空对象)
- Date(转换后变成了字符串,而非Date类的对象,JSON.parse只会把它们当成字符串,而不是日期类型。 )
- Symbol // 无
- 无法转换循环引用的对象
-
结构化克隆--html5的新算法 但是目前还不支持有些内置类型,但相比JSON.parse,他支持的类型要多得多,如:日期类型,Map, 正则表达式,集合,二进制大对象。
-
递归拷贝
var a = {a: 1,b: 2, c: 3, d: {a:1, b:2, c: 3}};
function deepClone(arr) {
if(arr.constructor !== Array || arr.constructor !== Object) return arr;
var clone = Array.isArray(arr) ? [] : {};
for(let key of arr.keys()) {
if(!isArray(arr[key])) {
deepClone(arr[key]);
} else if(arr[key].constructor === Object) {
deepClone(arr[key]);
} else {
clone[key] = arr[key];
}
}
return clone;
}
const ca = deepclone(a);
总结
浅拷贝和深拷贝取决于项目需要,一个对象的不同的拷贝方式,会产生不一样的效果。