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来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
随机推荐
- laravel 5.5 仓库模式 文件之间接口与实现操作
仓库模式 最直接的意思就是: Eloquent数据(数据库)查询 方便快捷,简单明了.自己怎么写的,就怎么去调用,完全ok~ 本质意思: 仓库就像是业务内部的数据对象集合,负责协调业务和数据映射层之 ...
- HTML 引用大全
路径logo <link rel="icon" href="../framework7-4.4.10/kitchen-sink/core/img/ztjs.png& ...
- 从0开始编写dapper核心功能、压榨性能、自己动手丰衣足食
我偶然听说sqlsugar的性能比dapper强.对此我表示怀疑(由于我一直使用的dapper存在偏见吧),于是自己测试了sqlsugar.freesql.dapper发现他们的给我的结果是 sqls ...
- JavaScript入门(二)
JavaScript入门—操作DOM树 要点 DOM树是一个树形结构,操作DOM树通常是“更新.遍历.新增.删除”. 更新DOM树 拿到DOM节点 var id=document.getElement ...
- 18 java I/O 系统
流的类继承结构 我们首先看看流的类继承结构,有助于理解下个标签的内容 InputStream OutputStream Reader Writer File类 File类技能表示一个特定文件的名称,又 ...
- tf.random_shuffle()函数解析
tf.random_shuffle(value, seed=None, name=None) 函数就是随机地将张量沿第一维度打乱 value:将被打乱的张量. seed:一个 Python 整数.用于 ...
- Java自学-类和对象 this
Java 中的 this this 这个关键字,相当于普通话里的"我" 小明说 "我吃了" 这个时候,"我" 代表小明 小红说 " ...
- jvm学习笔记之class文件的加载、初始化
编写的java文件在要真正运行时,会首先被编译成 “.class"结尾的二进制文件,然后被虚拟机加载.那么在虚拟机中一个class文件要成为java实例,需要经历好几个步骤: 1.装载:装载 ...
- 解决selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in P
转载 解决selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be i ...
- python中#!含义
LINUX 上的 Shebang 符号(#!) #!这个符号叫做 Shebang 或者 Sha-bangShebang 通常在 Unix 系统脚本的中第一行开头使用指明执行这个脚本文件的解释程序 使用 ...