JS中的浅拷贝与深拷贝
浅拷贝与深拷贝的区别:
浅拷贝:
对基本类型和引用类型只进行值的拷贝,即,拷贝引用对象的时候,只对引用对象的内存地址拷贝,新旧引用属性指向同一个对象,修改任意一个都会影响所有引用当前对象的变量。
深拷贝:
对引用类型所引用的对象也进行拷贝。使得新旧引用属性指向不同的对象,达到两者状态分离的效果。
实现方案:
方案一:
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中的浅拷贝与深拷贝的更多相关文章
- js中的浅拷贝和深拷贝
说说最近所学:浅拷贝和深拷贝也叫做浅克隆和深克隆,深浅主要针对的是对象的"深度",常见的对象都是"浅"的,也就是对象里的属性就是单个的属性,而"深&q ...
- 浅谈js中的浅拷贝和深拷贝
在js中如何把一个对象里的属性和方法复制给另一个对象呢? 下面举一个例子来说明: var person={name:'chen',age:18}; var son={sex:'男'}; functio ...
- 浅谈JS中的浅拷贝与深拷贝
前端工程师应该都比较熟悉浅拷贝和深拷贝的概念,在日常业务代码的过程中,特别是做数据处理的时候,经常行的会遇到,比如如何在不修改原对象的基础上,重新生成一个一模一样的对象,加以利用,又或是,如何巧妙地运 ...
- 【转】JAVA中的浅拷贝和深拷贝
原文网址:http://blog.bd17kaka.net/blog/2013/06/25/java-deep-copy/ JAVA中的浅拷贝和深拷贝(shallow copy and deep co ...
- 搞不懂JS中赋值·浅拷贝·深拷贝的请看这里
前言 百科定义:拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这 ...
- js对象的浅拷贝与深拷贝
浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用(堆和栈的关系,原始(基本)类型Undefined,Null,Boolean,Number和String是存入堆,直接引用,ob ...
- js 数组的浅拷贝和深拷贝
1.背景介绍 javascript分原始类型与引用类型.Array是引用类型,直接用"="号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,指向的是同一个内存地址,其中一个 ...
- Javascript中的浅拷贝和深拷贝
很多开发语言中都有浅拷贝和深拷贝的说法,这里简单区分一下它们在Javascript中的区别,以及jQuery中深拷贝的实现. 在谈浅拷贝和深拷贝之前,先要屡清楚Javascript中的按值访问和按引用 ...
- javascript中的浅拷贝和深拷贝(拷贝引用和拷贝实例)
作者:千锋教育链接:https://www.zhihu.com/question/23031215/answer/326129003来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
随机推荐
- GitLab CI/CD的官译【原】
CI / CD方法简介 软件开发的持续集成基于自动执行脚本,以最大限度地减少在开发应用程序时引入错误的可能性.从新代码的开发到部署,它们需要较少的人为干预甚至根本不需要干预. 它涉及在每次小迭代中不断 ...
- SQL Server中查找包含某个文本的存储过程 SQL 查找存储过程中出现过的文字怎么查询 查询整个数据库中出现的文本 sql 全局搜索
--将text替换成你要查找的内容SELECT name, *FROM sysobjects o, syscomments sWHERE o.id = s.id AND text LIKE '%tex ...
- java。JDK的API,版本1.6.0中文版下载
转载自https://blog.csdn.net/xiao9469/article/details/87783561 链接: https://pan.baidu.com/s/1YqrbTD_msTmn ...
- 【转载】C#中使用Insert方法往ArrayList集合指定索引位置插入新数据
ArrayList集合是C#中的一个非泛型的集合类,是弱数据类型的集合类,可以使用ArrayList集合变量来存储集合元素信息,在ArrayList集合操作过程中,可以使用ArrayList集合类的I ...
- 前端用js获取本地文件的内容
这里要写成input的形式 调用upload函数 传递的参数就表示所选的文件<input type="file" onchange="upload(this)&qu ...
- GoLang 中用 MongoDB Watch 监听指定字段的变化
需要 MongoDB 3.6 及以上, 需要 ReplicaSet 模式. 监听一个字段的变化: func watch(coll *mongo.Collection) { match := bson. ...
- windows jupyter notebook 切换默认环境
windows jupyter notebook 切换默认环境 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog ...
- windows创建虚拟环境
mkvirtualenv --no-site-packages --python=C:\Python36\python.exe MyCrawler
- Socket网络编程-UDP编程
Socket网络编程-UDP编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.UDP编程概述 1>.UDP服务端编程流程 创建socket对象.socket.SOCK_ ...
- Ugly Pairs CodeForces - 1156B
题目链接:https://vjudge.net/problem/CodeForces-1156B 题意:给定一串字符,相邻字符的ASCII码不能是相邻的数字,比如ABC,假设ASCII码为,99 10 ...