JS拷贝对象 浅克隆深克隆 深拷贝浅拷贝
对象简介
js程序中都是用对象结构来描述显示中一个事物对象就是一组属性和方法的集合。
面向对象三大特点: 封装继承多态。
克隆对象
浅克隆是克隆 一层深层次的对象级别的就克隆引用地址 深克隆是克隆 多层每一级别的数据都会克隆出来 浅克隆就是克隆了一层除了对象是克隆的引用类型地址其他都是 按值传递有自己的内存空间
点击进入查看按值传递
实现浅克隆方法
for in循环
//------------------1------------------function clone(initalObj) {var obj {};for ( var i in initalObj) {obj[i] initalObj[i];}return obj;}//------------------2------------------var obj {a: "hello",b:{a: "world",b: 21},c:["Bob", "Tom", "Jenny"]};//------------------3------------------var cloneObj clone(obj);//------------------4------------------console.log(cloneObj.a);console.log(cloneObj.b);console.log(cloneObj.c);//------------------5------------------cloneObj.a "changed";cloneObj.b.a "changed";cloneObj.b.b 25;cloneObj.c[3] "Lilei";//------------------6------------------console.log(obj.a); //helloconsole.log(obj.b); //{a:"changed",b:25}console.log(obj.c); //[Bob,Tom,Jenny,Lilei]
通过以上代码可以看出来obj.b 属性的属性值被 修改 cloneObj.b 值的时候修改 c 和 b 是同样的结果
事实上就是for in循环 克隆引用类型的时候复制的都是引用地址
ES6中的Object.assign方法
Object.assign(target, ...sources)//参数//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); //LiLeiconsole.log(obj.b.a); // "changed"var obj2 { a: 1, b: 2, c: 3 };var cloneObj2 Object.assign({}, obj2);cloneObj2.b 10;console.log(obj2);// { a: 1, b: 2, c: 3 }console.log(cloneObj2);// { a: 1, b: 10, c: 3 }
可以看到修改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(objnull){return null;}if({}.toString.call(obj)"[object Array]"){var newArr[];newArrobj.slice();return newArr;}var newobj{};//遍历对象中的每个属性for(var key in obj){//如果原对象中当前值是原始类型就可以直接赋值if(typeof obj[key]!"object"){//在新对象中添加和原对象中同名的属性newobj[key]obj[key];//因为原始类型复制就是复制副本}else{//否则当前属性不是原始类型的值再次调用clone函数继续复制当前属性值newobj[key]clone(obj[key])}}return newobj;}var LiMingclone(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);// { LiLei: { age: 21 } }console.log(obj2);// { LiLei: { age: 25 } }console.log(obj1 obj2);// falseconsole.log(obj1.body obj2.body);// false
可以看到克隆出来的对象和原对象除了长的相似别的已再无关系。
注: 使用 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); //{"LiLei":{"age":21},"isLilei":{},"car":["二手奥拓",["五菱之光"],{},null,null]}
从以上结果可知这种方法能正确处理的对象只有 Number, String, Boolean即那些能够被 json 直接表示的数据结构。
Object.create()方法
Object.create(proto[, propertiesObject]) 仅靠父对象就可以创建子对象的一个方法。
Object.create(proto[, propertiesObject])//参数//proto新创建对象的原型对象//propertiesObject可选。如果没有指定为 undefined则是要添加到新创建对象的不可枚举默认属性即其自身定义的属性而不是其原型链上的枚举属性对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。//返回值//一个新对象带着指定的原型对象和属性。
如下代码
var obj {x: 1,y: {a: 1,b: 0,c: [1, 2, 3]}};var obj2 Object.create(obj);console.log(obj2 obj); //falseconsole.log(obj2);
在输出结果中可以看到obj2自己并没有属性属性全部都是继承于父对象