浅拷贝与深拷贝的区别:

浅拷贝:
对基本类型和引用类型只进行值的拷贝,即,拷贝引用对象的时候,只对引用对象的内存地址拷贝,新旧引用属性指向同一个对象,修改任意一个都会影响所有引用当前对象的变量。 深拷贝:
对引用类型所引用的对象也进行拷贝。使得新旧引用属性指向不同的对象,达到两者状态分离的效果。

实现方案:

方案一:

Object.assign()方法可以用于合并对象,并且只在顶层属性上进行合并。

var obj1 = { x: 1, y: 2 },
obj2 = Object.assign({}, obj1);
console.log(obj1); //{x: 1, y: 2}
console.log(obj2); //{x: 1, y: 2}
obj2.x = 2; //修改obj2.x
console.log(obj1); //{x: 1, y: 2}
console.log(obj2); //{x: 2, y: 2}

缺点:只实现了合并时顶层这一层的深拷贝。

方案二:

JSON.parse(JSON.stringify(obj))利用 JSON 对象中转一次,实现深拷贝。

var obj1 = {
x: 1,
y: {
m: 1
}
};
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1); //{x: 1, y: {m: 1}}
console.log(obj2); //{x: 1, y: {m: 1}}
obj2.y.m = 2; //修改obj2.y.m
console.log(obj1); //{x: 1, y: {m: 1}}
console.log(obj2); //{x: 2, y: {m: 2}}

缺点:由于 JSON 对象转化规则,undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)且只适用于能够用 JSON 表示的对象。

例子:

var obj1 = {
x: 1,
y: undefined,
z: function add(z1, z2) {
return z1 + z2;
},
a: Symbol("foo")
};
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1); //{x: 1, y: undefined, z: ƒ, a: Symbol(foo)}
console.log(JSON.stringify(obj1)); //{"x":1}
console.log(obj2); //{x: 1}

方案三:

使用 for in 遍历原型以及自身所有可枚举属性,在遇到 object 时递归自身完成对象深拷贝。

var deepClone = function fnDeepClone(obj) {
var result = typeof obj.splice === "function" ? [] : {},
key;
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj[key] && typeof obj[key] === "object") {
result[key] = fnDeepClone(obj[key]); //如果对象的属性值为object的时候,递归调用deepClone,即再把某个值对象复制一份到新的对象的对应值中
} else {
result[key] = obj[key]; //如果对象的属性值不为object的时候,直接复制参数对象的每一个键/值到新对象对应的键/值中
}
}
return result;
}
return obj;
}; var obj1 = {
family: { brother: "wangzhipeng", father: "wanglicai", mother: "sunaiyun" },
name: "gino",
sex: "male",
age: "27",
test: undefined,
a: Symbol("foo"),
f() {}
};
var obj2 = deepClone(obj1);
obj1.sex = "close";
obj2.age = "33";
obj1.f = () => {
console.log(1111);
};
console.log(obj1);
console.log(obj2);

缺点:只支持object和array类型

方案四:

使用 Object.create 以 obj 原型创建一个对象,然后使用 Objcet.getOwnPropertyDescriptors 获取对象属性描述符数组来创建这个对象。

var deepClone = function(o) {
var copy = Object.create(
Object.getPrototypeOf(o),
Object.getOwnPropertyDescriptors(o)
);
return copy;
}; var obj1 = {
family: { brother: "wangzhipeng", father: "wanglicai", mother: "sunaiyun" },
name: "gino",
sex: "male",
age: "27"
f(){ }
};
var obj2 = deepClone(obj1);
obj1.sex = "close";
obj2.age = "33";
console.log(obj1);
console.log(obj2);

优点:在对象属性中允许函数、undefined、Symbol 拷贝,还能继承原型

总结:

以上方法暂未实现包装对象,Date对象,正则对象的深拷贝,尚未验证DOM对象深拷贝后功能函数是否正常,对于后台JSON对象拷贝,已经足够

JS中的浅拷贝与深拷贝的更多相关文章

  1. js中的浅拷贝和深拷贝

    说说最近所学:浅拷贝和深拷贝也叫做浅克隆和深克隆,深浅主要针对的是对象的"深度",常见的对象都是"浅"的,也就是对象里的属性就是单个的属性,而"深&q ...

  2. 浅谈js中的浅拷贝和深拷贝

    在js中如何把一个对象里的属性和方法复制给另一个对象呢? 下面举一个例子来说明: var person={name:'chen',age:18}; var son={sex:'男'}; functio ...

  3. 浅谈JS中的浅拷贝与深拷贝

    前端工程师应该都比较熟悉浅拷贝和深拷贝的概念,在日常业务代码的过程中,特别是做数据处理的时候,经常行的会遇到,比如如何在不修改原对象的基础上,重新生成一个一模一样的对象,加以利用,又或是,如何巧妙地运 ...

  4. 【转】JAVA中的浅拷贝和深拷贝

    原文网址:http://blog.bd17kaka.net/blog/2013/06/25/java-deep-copy/ JAVA中的浅拷贝和深拷贝(shallow copy and deep co ...

  5. 搞不懂JS中赋值·浅拷贝·深拷贝的请看这里

    前言 百科定义:拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这 ...

  6. js对象的浅拷贝与深拷贝

    浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用(堆和栈的关系,原始(基本)类型Undefined,Null,Boolean,Number和String是存入堆,直接引用,ob ...

  7. js 数组的浅拷贝和深拷贝

    1.背景介绍 javascript分原始类型与引用类型.Array是引用类型,直接用"="号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,指向的是同一个内存地址,其中一个 ...

  8. Javascript中的浅拷贝和深拷贝

    很多开发语言中都有浅拷贝和深拷贝的说法,这里简单区分一下它们在Javascript中的区别,以及jQuery中深拷贝的实现. 在谈浅拷贝和深拷贝之前,先要屡清楚Javascript中的按值访问和按引用 ...

  9. javascript中的浅拷贝和深拷贝(拷贝引用和拷贝实例)

    作者:千锋教育链接:https://www.zhihu.com/question/23031215/answer/326129003来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

随机推荐

  1. springboot WebMvcConfigurer配置静态资源和解决跨域

    前言 虽然现在都流行前后端分离部署,但有时候还是需要把前端文件跟后端文件一起打包发布,这就涉及到了springboot的静态资源访问的问题.不单只是静态资源打包,比如使用本地某个目录作为文件存储,也可 ...

  2. drf之视图类与路由

    视图 Django REST framwork 提供的视图的主要作用: 控制序列化器的执行(检验.保存.转换数据) 控制数据库查询的执行 2个视图基类 APIView rest_framework.v ...

  3. Java 之 匿名对象

    一.匿名对象 创建对象时,只有创建对象的语句,却没有把对象地址赋值给某个变量. 虽然是创建对象的简化写法,但是应用场景非常有限. 匿名对象:没有变量名的对象. 语法格式: new 类名(参数列表): ...

  4. 创建简易的SpringBoot项目

    创建简易的SpringBoot项目 这两天在学习springboot,菜鸟刚刚知道这个东西,看着springboot项目下那一大堆目录都不知道从何下手,还是静下心来从最简单的创建一个项目入手,这路和大 ...

  5. SparkStreaming之checkpoint检查点

    一.简介 流应用程序必须保证7*24全天候运行,因此必须能够适应与程序逻辑无关的故障[例如:系统故障.JVM崩溃等].为了实现这一点,SparkStreaming需要将足够的信息保存到容错存储系统中, ...

  6. Protobuf协议应用干货

    Protobuf应用广泛,尤其作为网络通讯协议最为普遍.本文将详细描述几个让人眼前一亮的protobuf协议设计,对准备应用或已经应用protobuf的开发者会有所启发,甚至可以直接拿过去用. 这里描 ...

  7. Linux服务器相关信息查询

    链接:https://www.cnblogs.com/luoahong/articles/8781375.html 机器型号dmidecode | grep "Product Name&qu ...

  8. 前后端分离结构中使用shiro进行权限控制

    前阵子在前后端分离项目中集成shiro项目,折腾了一下子,参考了网上一些博客,发现大多都还是之前传统的模式,并不适用于前后端分离结构.今天抽空整理了下demo,方便以后使用以及后来人参考. 一.spr ...

  9. 【BZOJ 4004】 装备购买(高斯消元+贪心)

    装备购买 题目 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 <= j ...

  10. 201671030106 何启芝 实验十四 团队项目评审&课程学习总结

    项目 内容 这个作业属于哪个课程 >>2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 >>实验十四 团队项目评审&课程学习总结 课程学习目 ...