JS拷贝对象 浅克隆深克隆 深拷贝浅拷贝
对象简介
js程序中都是用对象结构来描述显示中一个事物,对象就是一组属性和方法的集合。
面向对象三大特点: 封装,继承,多态。
克隆对象
浅克隆是克隆 一层,深层次的对象级别的就克隆引用地址
深克隆是克隆 多层,每一级别的数据都会克隆出来
浅克隆就是克隆了一层,除了对象是克隆的引用类型地址,其他都是 按值传递,有自己的内存空间
点击进入查看按值传递
实现浅克隆方法
for in循环
- 定义一个克隆函数用循环一个一个把对象中的属性赋值强行添加给新对象
- 创建一个对象,对象的属性有:字符串,对象,数组
- 调用克隆函数,把刚刚创建的对象放进去
- 分别输出得到对象的三个属性值
- 更改克隆生成的对象中的a,b,c
- 看看原来的对象是否变化
function clone(initalObj) {var obj = {};for ( var i in initalObj) {obj[i] = initalObj[i];}return obj;
}
var obj = {a: "hello",b:{a: "world",b: 21},c:["Bob", "Tom", "Jenny"]
};
var cloneObj = clone(obj);
console.log(cloneObj.a);
console.log(cloneObj.b);
console.log(cloneObj.c);
cloneObj.a = "changed";
cloneObj.b.a = "changed";
cloneObj.b.b = 25;
cloneObj.c[3] = "Lilei";
console.log(obj.a);
console.log(obj.b);
console.log(obj.c);
通过以上代码可以看出来,obj.b
属性的属性值被 修改 cloneObj.b
值的时候修改 c
和 b
是同样的结果
事实上就是for in
循环 克隆引用类型的时候,复制的都是引用地址
ES6中的Object.assign方法
Object.assign(target, ...sources)
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
但是 Object.assign()
进行的是浅克隆,克隆的是对象的属性的引用,而不是对象本身。
var obj = {a: "LiLei",b: {a: "LiXiaolei",b: 21,},};
var cloneObj = Object.assign({}, obj);
cloneObj.a = "changed";
cloneObj.b.a = "changed";console.log(obj.a);
console.log(obj.b.a); var obj2 = { a: 1, b: 2, c: 3 };
var cloneObj2 = Object.assign({}, obj2);
cloneObj2.b = 10;
console.log(obj2);
console.log(cloneObj2);
可以看到修改cloneObj2.b
,原来obj2
没有发生变化
实现深克隆方法
递归拷贝
定义函数在函数执行前判断类型:
是否为null
、是就直接返回null
;
是否为数组,是数组利用slice
方法放到一个新数组返回;
在遍历的时候判断是否为引用类型,如果原对象中当前值是原始类型就可以直接赋值,否则当前属性不是原始类型的值,再次调用clone
函数,继续复制当前属性值
var LiMing={sname:'LiMing',sage:11,score:null,firends:["jack","rose"],address:{prov:'北京',city:'北京',area:'朝阳',street:'成寿寺'}
}
function clone(obj){if(obj===null){return null;}if({}.toString.call(obj)==="[object Array]"){var newArr=[];newArr=obj.slice();return newArr;}var newobj={};for(var key in obj){if(typeof obj[key]!=="object"){newobj[key]=obj[key];}else{newobj[key]=clone(obj[key])}}return newobj;
}
var LiMing=clone(LiMing);
JSON.parse(JSON.stringify(obj));
JSON.stringify()
方法用于将 Javascript 值(通常为对象或数组)转换为 JSON 字符串。
JSON.parse()
方法用于将一个 JSON 字符串转换为对象。
用JSON.stringify
把对象转成字符串,再用JSON.parse
把字符串转成新的对象。
建议先看下 JSON.stringify()方法 --> 传送门
var obj1 = { LiLei: { age: 21 } };var obj2 = JSON.parse(JSON.stringify(obj1));obj2.LiLei.age = 25;console.log(obj1);console.log(obj2);console.log(obj1 === obj2);console.log(obj1.body === obj2.body);
可以看到克隆出来的对象和原对象除了长的相似,别的已再无关系。
注: 使用 JSON.stringify()方法时,undefined、任意的函数以及 symbol 值,出现在非数组对象的属性值中时会被忽略,出现在数组中时被转换成 null。函数、undefined 被单独转换时,会返回 undefined。
请看下边的例子:
var obj1 = { LiLei: { age: 21 },isLilei: new RegExp(/\w+/),money:undefined,speak:function(){console.log(`I am ${this.sname}`) },car:["二手奥拓",['五菱之光'],new RegExp(/\w+/),undefined,function haha(){console.log("hello")}],};var obj2 = JSON.stringify(obj1);
从以上结果可知这种方法能正确处理的对象只有 Number, String, Boolean,即那些能够被 json 直接表示的数据结构。
Object.create()方法
Object.create(proto[, propertiesObject])
仅靠父对象就可以创建子对象的一个方法。
Object.create(proto[, propertiesObject])
如下代码:
var obj = {x: 1,y: {a: 1,b: 0,c: [1, 2, 3]}
};var obj2 = Object.create(obj);
console.log(obj2 == obj);
console.log(obj2);
在输出结果中可以看到,obj2自己并没有属性,属性全部都是继承于父对象