JavaScript 克隆
日常开发当中经常会遇到由于js引用数据类型导致的开发烦恼,Now,我们就来谈一谈js当中的一些克隆方式方法;
首先js克隆基本分为浅克隆、深克隆两种方式
克隆前传
我们知道在引用数据类型当中如:对象、数组这样的都是一个地方存储数据一个地方存储地址,一般就是说的栈来存地址数据则是存储在堆当中的。
例如:
1 | let a = {b:1} |
好了,咱们go on。
- 浅克隆
浅克隆很明显就是很浅的克隆不会把深层次的数据克隆(说了像没说);意思是对于复杂类型的数据来说,它只是克隆了对象地址,而真正的数据是没有克隆的;原始数据改了,它也会以一并被更改。
我们来看个列子:
1 | let a = {a:1}; |
常见的浅克隆 :
1.Object.assign()
1 | let a = {a:1}; |
2.对于数组.slice()
如果数组每项数据全为基本类型,复制可理解为深克隆,如果存在引用数据类型,为浅克隆;
3.对于 JSON.parse(JSON.stringify(data)); 方法能满足大部分需要,能解释为深克隆,但是他不能克隆函数,所以说也会存在问题。
深克隆
因为浅克隆的问题都是由于存在引用数据类型的复杂数据导致的,深克隆的基本原理则是,遍历递归原始数据,如果遇到是基本数据则直接赋值,如果是复杂类型数据,将其递归。
大致代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36//获取当前数据类型
function getObjectType(obj){
var objType = '';
if(obj === null){
objType = 'null';
}else if(obj === undefined){
objType = 'undefined';
}else{
objType = Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
}
return objType;
}
//执行主函数
function deepClone(obj){
var res;
var objType = getObjectType(obj);
if(objType === 'object'){
res = {};
for(var key in obj){//
/*
因为for ... in 为遍历出原型链上的数据,如果不需要则需加上判断
obj.hasOwnProperty(key) === true
*/
res[key] = deepClone(obj[key]);//arguments.callee代表函数名 这里也可以写成 res[key] = arguments.callee(obj[key]);
}
}else if(objType === 'array'){
res = [];
for(var i = 0 , len = obj.length; i < len ; ++i){
res[i] = deepClone(obj[i]);
}
}else{
res = obj;
}
return res;
}