一、js中的对象
谈到对象的克隆,必定要说一下对象的概念。
js中的数据类型分为两大类:原始类型和对象类型。(1)原始类型包括:数值、字符串、布尔值、null、undefined(2)对象类型包括:对象即是属性的集合,当然这里又两个特殊的对象—-函数(js中的一等对象)、数组(键值的有序集合)。
好了既然对象分为这两类,这两种类型在复制克隆的时候是有很大区别的。原始类型存储的是对象的实际数据,而对象类型存储的是对象的引用地址(对象的实际内容单独存放,为了减少数据开销通常存放在内存中)。ps:说到这里,大家要知道,对象的原型也是引用对象,它把原型的方法和属性放在内存当中,通过原型链的方式来指向这个内存地址。
二、克隆的概念
浅度克隆:原始类型为值传递,对象类型仍为引用传递。
深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。
Object.assgin 只能深拷贝第一层, 深层的还是浅拷贝
浅复制例子
var obj={"a":1,"b":2}
var objClone = obj;
obj.a=3;
console.log(obj);///{"a":3,"b":2}变了
console.log(objClone);///{"a":3,"b":2}也变了
深克隆例子
function deepClone(x){
var y={};
for(i in x){
y[i] = (typeof(x[i])==='object')?deepClone(x[i]):x[i]; //递归
}
return y;
}
var obj={"a":1,"b":2}
var objClone = deepClone(obj);
obj.a=3;
console.log(obj);//{"a":3,"b":2}变了
console.log(objClone);//{"a":1,"b":2}未变,哇哇
数组和对象通用的,深拷贝:
function deepCopy(source, target = {}) {
var key;
for (key in source) {
if (source.hasOwnProperty(key)) {//意思就是__proto__上面的属性,我不拷贝
if (typeof(source[key]) === "object") {//如果这一项是object类型,就递归调用deepCopy
target[key] = Array.isArray(source[key]) ? [] : {};
deepCopy(source[key], target[key]);
} else {// 如果不是object类型,就直接赋值拷贝
target[key] = source[key];
}
}
}
return target;
}
又一个例子
要实现深复制有很多办法,比如最简单的办法有:
var cloneObj = JSON.parse(JSON.stringify(obj));
JSON.parse(JSON.stringify(obj))一般用来深拷贝一个json对象吧,还可以用来去除值不具有JSON 表示形式(数字、字符串、逻辑值、数组、对象、null)的属性,也就是说像undefined和function这样的属性值。如:
a: {
age: 1,
name: undefined,
time: () => {...}
}
变成:
b: {
age: 1
}
题外话
例题:请写一个函数,将一个多维数组的值提取成一串字符串
var arr2 = [];
function turnStr(arr){
for(var i in arr){
if(arr[i] instanceof Array){
turnStr(arr[i]);
}else{
arr2.push(arr[i])
}
}
return arr2;//[1,2,3,4,5,6,7]
}
var arr=[1,[2,[3]],[4,[5,[6,[7]]]]];
var arrStr=turnStr(arr).join('');//turn arr to string
console.log(arrStr);//"1,2,3,4,5,6,7"