JS-对象的深浅拷贝及其新增方法测试
我们在了解数据类型的时候,都知道一般的字符,数值,undefined和布尔值等都为一般数据类型,它们在进行数据传输的时候,进行的是值传递,当我们修改新数据,是不影响老数据的。但是我们今天要讲的是数据类型中的一种复杂数据,它的代表就是对象。
// 一般数据的值拷贝
// 将a的值作为实参传入函数执行函数语句,虽然函数体内的参数发生了改变
// 却不会影响原数据的值
var a = 10 ;
function fn(a){
a = 20;
console.log(a); //20
}
fn(a);
console.log(a); //10
对象的传递是一种引用传递,当发生数据的拷贝时,对象传递的是内存地址的指向,将两个变量的指向拉到同一个地址上去了,这就会导致当我们对新拷贝数据进行修改的时候,老数据也会受到影响,值也会发生改变,但这种改变是一定的么?那也不一定,这就引入了我们今天要测试的内容:对象的深浅拷贝。
首先我们先来测试一下浅拷贝,浅拷贝简单来说就是对象只拷贝了地址,不拷贝值,这种情况就会导致我们上面所说的情况,具体代码测试如下:
// 对象的浅拷贝:
//声明对象并赋值
var obj = {
name:"admin"
}
// 创建函数进行拷贝
function fn(obj2){
// 执行语句将obj2的name值改为root
obj2.name = "root"
}
//执行函数并将obj的值传参给函数
fn(obj);
// 打印返回obj,此时obj的值发生了改变
console.log(obj); //{name:"root"}
另一种就是我们今天要着重要介绍的深拷贝,与浅拷贝恰恰相反,深拷贝是只拷贝原对象的值,不拷贝地址,而这种拷贝模式就会让我们在处理对象数据拷贝问题时,可以在拷贝数据的同时不影响老数据。一般实现的方法如下:
// 对象的深拷贝
// 一般我们利用for in对对象实现遍历达到深拷贝的目的
var obj = {
name :"admin"
}
// 声明空对象
var obj2 = {};
// 遍历老对象,赋值给新对象
for(var i in obj){
// 这里的赋值仅为值的拷贝,并没有拷贝地址
obj2[i]=obj[i];
}
// 改变新对象的值
obj2.name = "root";
// 返回结果并未对老对象的值产生影响
console.log(obj); //{name:"admin"}
console.log(obj2); //{name:"root"}
通过上面的测试我们可以得出for in的遍历可以实现对对象的深拷贝,但是它就是完美无缺的么?答案肯定是否定的,下面看一种特殊的对象拷贝情景,来测试for in 拷贝的特点:
// 特殊对象的拷贝,测试for in的深拷贝特点
var obj = {
name:{
name:"admin"
}
}
var obj2 = {};
// 遍历老对象,赋值给新对象
for(var i in obj){
obj2[i] = obj[i]
}
// 测试第一层值是否被深拷贝 (结果是成立的)
// obj2.name = "root";
// console.log(obj); //{name:name:"admin"}
// console.log(obj2); //{name:"root"}
// 测试第二层值是否被深拷贝 (结果是否定的)
obj2.name.name = "root";
console.log(obj); //{name:name: "root"}
console.log(obj2); //{name:name: "root"}
// 继续测试如果对象有两层以上的值时,for in就实现不了对对象的深拷贝。
// 例 :var obj = {
// name:{
// name:{
// name:"admin"
// }
// }
// }
// 感兴趣的朋友可以自行测试
// 由此引出for in遍历只能实现一层深拷贝的特点
for in只能实现一层深拷贝,那有什么方法是可以实现对对象完全的深拷贝呢?答案当然也是肯定的,在ES5中我们将会了解到JSON.parse(str)和JSON.stringify(obj)两种实现json/对象的序列化和反序列化的方法,这里我简单介绍一下,JSON.parse(str)是用来将json字符转化成对象的方法,而JSON.stringify(obj)则是将对象转化为json字符串的方法。利用这两种方法我们来实现对象深拷贝的另一种方法:
// 特殊对象的拷贝,测试JSON.parse(str)和JSON.stringify(obj)的深拷贝
var obj = {
name:{
name:"admin"
}
}
var obj2 = JSON.parse(JSON.stringify(obj));
// 利用JSON.stringify(obj)将obj对象转化为json,再将json通过JSON.parse()重新转化为一个新的对象赋值给obj2;
// 测试第一层值是否被深拷贝 (结果是成立的)
// obj2.name = "root";
// console.log(obj); //{name:name:"admin"}
// console.log(obj2); //{name:"root"}
// 测试第二层值是否被深拷贝 (结果是成立的)
obj2.name.name = "root";
console.log(obj); //{name:name: "admin"}
console.log(obj2); //{name:name: "root"}
// 即使是三层测试结果同样是成立的
由此可得对象完全深拷贝新黑科技。
JS-对象的深浅拷贝及其新增方法测试的更多相关文章
- js对象的深浅拷贝
JS数据类型可以分为(ES5,暂时不考虑ES6): 简单数据类型:Number.String.undefined.boolean 复杂数据类型:Object.Array 简单的数据类型,往往是赋值操作 ...
- 关于Java的Object.clone()方法与对象的深浅拷贝
文章同步更新在个人博客:关于Java的Object.clone()方法与对象的深浅拷贝 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Object.clon ...
- js中的深浅拷贝
js中的深浅拷贝 js中有深拷贝.浅拷贝一说,所谓的深浅拷贝是针对value类型为引用类型(函数.对象.数组)而言的,大概理解的就是: 浅拷贝: 拷贝出的对象c和原始对象o,c和o在key对应的val ...
- C#在WinForm中使用WebKit传递js对象实现与网页交互的方法
这篇文章主要介绍了C#在WinForm中使用WebKit传递js对象实现与网页交互的方法,涉及针对WebBroswer控件及WebKit控件的相关使用技巧,需要的朋友可以参考下 本文实例讲述了C#在W ...
- JS复习之深浅拷贝
一.复习导论(数据类型相关) 想掌握JS的深浅拷贝,首先来回顾一下JS的数据类型,JS中数据类型分为基本数据类型和引用数据类型. 基本数据类型是指存放在栈中的简单数据段,数据大小确定,内存空间大小可以 ...
- 【 js 基础 】 深浅拷贝
underscore的源码中,有很多地方用到了 Array.prototype.slice() 方法,但是并没有传参,实际上只是为了返回数组的副本,例如 underscore 中 clone 的方法: ...
- 超实用的JavaScript代码段 Item8 -- js对象的(深)拷贝
js 对象 浅拷贝 和 深拷贝 1.浅拷贝 拷贝就是把父对像的属性,全部拷贝给子对象. 下面这个函数,就是在做拷贝: var Chinese = { nation:'中国' } var Doctor ...
- 判断JS对象是否拥有某属性的方法举例
判断JS对象是否拥有某属性 JS是否拥有某属性的判断方法,这里提供两种方式,供大家参考. 1.in 运算符 var obj = {name:'jack'}; alert('name' in obj); ...
- Object.clone()方法与对象的深浅拷贝
转载:[https://www.cnblogs.com/nickhan/p/8569329.html] 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Obj ...
随机推荐
- centos7下yum方式安装MySQL5.7
前言: MySQL作为一款免费.开源数据库产品,已经问世就饱受关注,很多中小企业甚至是大企业都钟爱MySQL,随着大数据的不断发展,我们接触的信息量也越来越多,虽然NoSQL是大数据的宠儿,但MySQ ...
- 树状数组(binary index tree)
概述 修改和查询复杂度为log(n)的数据结构,所有奇数位的数和原数位置相同,偶数位置是原数组若干位置的和. 假如原数组A(a1, a2, a3, a4 ...),和其对应的树状数组C(c1, c2, ...
- Ubuntu启动Apache
划重点:最重要的是找到一个文件--------startup.sh 如果你是按照百度上的方法下载的Apache2,那么就按照百度的方式来 但是异曲同工 如果你是自己在网上下载的Apache到的磁盘 找 ...
- ES6--变量
声明变量 首先我们来回顾一下 es6 之前声明变量的方法:通常情况下,在 JavaScript 中,我们只有一种声明变量的关键字--var,我们使用 var 声明变量,使用 = 给变量赋值.在es6中 ...
- Angular JS 中 ng-controller 值复制和引用复制
我们知道在使用ng-app或者ng-controller指令的时候,都会创建一个新的作用域($rootScope或者是$scope),并且在使用ng-controller指令创建的作用域会继承父级作用 ...
- 【MySQL】java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\xB3' for column
问题原因: 输入内容包含特殊字符,MySQL 中的列不支持. 解决方法 多数是修改 MySQL 的数据库和表结构,CHARSET 改为 utf8mb4,但本人测试还是不能传入 emoji. 后来在代码 ...
- 【Java】You have an error in your SQL syntax ...
详情如下: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server v ...
- iOS 注释
1) 参数的注释: UIButton *btnSend;/**< 发送按钮 */ 效果: 2) 方法的注释: type1(无参数): /** table 相关设置 */ -(void)confi ...
- .NET Core on K8S学习实践系列文章索引(Draft版)
一.关于这个系列 自从去年(2018年)底离开工作了3年的M公司加入X公司之后,开始了ASP.NET Core的实践,包括微服务架构与容器化等等.我们的实践是渐进的,当我们的微服务数量到了一定值时,发 ...
- TCP重置报文段及RST常见场景分析
RST表示连接重置,用于关闭那些已经没有必要继续存在的连接.一般情况下表示异常关闭连接,区别与四次分手正常关闭连接. 产生RST的三个条件是: 目的地为某端口的SYN到达,然而在该端口上并没有正在监听 ...