blog
blog copied to clipboard
JS深拷贝碰到的问题
js的数据类型有:Null Undefined Boolean Number Array String Object 之分,es6后又增加了Symbol, 其中分为2大类:基本数据类型和对象类型,同时产生了相应的2个传值方式:赋值和引用;
基本数据类型的深拷贝
JSON.parse(JSON.stringify(obj))
通过简单函数
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
return c;
}
引用类型深拷贝
引用类型细分
- 基本的JS对象:正则,函数,对象,数组等之分
- 其他JS内置的Date,Error,Math等
- 浏览器内置的window,document等
严格来说,这些对象赋值时都是要考虑的,但常见的对象内部存放的数据类型不会涵盖的这么全面, 但也需要考虑:正则,函数,对象,数组,Dete,Dom
数据类型的识别办法
var type=Object.prototype.toString.call(Obj).split(/[\[\s\]]/)[2]
通过识别type可以确认数据的类型,然后分别针对Array,Object做不同的处理
let obj1 = {
a: 11,
b: 'bb',
c: new Date(),
d: function aa () {return 2},
e:[1,2,3],
f:new Error('error'),
g:document.body,
h:new RegExp(/[111]/)
}
function deepCopy (obj) {
var type = Object.prototype.toString.call(obj).split(/[\[\s\]]/)[2];
let temp = type === 'Array' ? [] : type=='Object'? {}:obj;
if(type=='Array' || type=='Object'){
for (let val in obj) {
temp[val] = typeof obj[val] == 'object' ? deepCopy(obj[val]) : obj[val]
}
}
return temp
}
如上,实现了深拷贝
但深拷贝还有一个坑要填
那就是循环赋值问题;回到前面的
··· let obj1 = { a: 11, b: 'bb', c: new Date(), d: function aa () {return 2}, e:[1,2,3], f:new Error('error'), g:document.body, h:new RegExp(/[111]/), } obj1.g=obj1 deepCopy(obj1)
//Uncaught RangeError: Maximum call stack size exceeded
at RegExp.[Symbol.split] (
这是就会出现堆栈溢出的错误了。