浅拷贝与深拷贝的区别:

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

实现方案:

方案一:

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. 关于vs无法创建虚拟目录的问题

    插入链接:https://blog.csdn.net/zhao1955/article/details/92182935 补充:改完之后不要忘记以管理员的身份运行vs

  2. .NET Core 傻瓜式CSRedisCore缓存

    作者:依乐祝原本链接:https://www.cnblogs.com/yilezhu/p/9947905.html 需要安装Redis   => https://www.runoob.com/r ...

  3. Java自学-操作符 关系操作符

    Java的关系操作符 关系操作符:比较两个变量之间的关系 > 大于 >= 大于或等于 < 小于 <= 小于或等于 == 是否相等 != 是否不等 示例: public clas ...

  4. Dubbo 几个很实用但是很少人知道的功能

    dubbo功能非常完善,很多时候我们不需要重复造轮子,下面列举一些你不一定知道,但是很好用的功能; 直连Provider 在开发及测试环境下,可能需要绕过注册中心,只测试指定服务提供者,这时候可能需要 ...

  5. spec开发思路以及理解

    一.spec说明 描述:编写SEPC采用创联公司自主开发的CIT语言,它是一种过程化的.类似数据库编码的语言.SPEC中除了关键字外提倡使用中文. 理解:可以理解为业务逻辑层.链接前台页面和后台数据库 ...

  6. Integrated SOA Gateway 不是当前用户的有效责任。请联系您的系统管理员。

    问题:给用户新增职责集成SOA网关,点击路径进入时出现报错:"Integrated SOA Gateway 不是当前用户的有效责任.请联系您的系统管理员." 解决:功能管理员职责, ...

  7. Mac OS 查看端口和杀死进程

    查看sudo lsof -i:port (端口号) sudo lsof -i:9501 COMMAND PID USER FD TYPE DEVICESIZE/OFF NODE NAME php 77 ...

  8. python 导入导出依赖包命令

    程序中必须包含一个 requirements.txt 文件,用于记录所有依赖包及其精确的版本号.如果 要在另一台电脑上重新生成虚拟环境,这个文件的重要性就体现出来了,例如部署程序时 使用的电脑.pip ...

  9. 基于python3环境使用bandersnatch搭建本地pypi源

     pip3 install bandersnatch # https://pypi.org/project/bandersnatch/#files 查询最新版本 wget https://files. ...

  10. 初步学习JAVA面向对象初步认识及面向对象内存分析图举例说明

    1. 说到面向对象, 一个绕不开的话题,就是面向过程. 面向过程适合简单.不需要协作的事务. 面向过程 = 分解问题 + 逻辑为先 = 先细节,再整体. 对比面向过程, 面向对象是模块化的, 当我们思 ...