【 js 基础 】 深浅拷贝
// Create a (shallow-cloned) duplicate of an object.
// 对象的 `浅复制` 副本
// 注意点:所有嵌套的对象或者数组都会跟原对象用同一个引用
// 所以是为浅复制,而不是深度克隆
_.clone = function(obj) {
// 容错,如果不是对象或者数组类型,则可以直接返回
// 因为一些基础类型是直接按值传递的
if (!_.isObject(obj))
return obj; // 如果是数组,则用 obj.slice() 返回数组副本
// 如果是对象,则提取所有 obj 的键值对覆盖空对象,返回
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
var a = ["a","b","c"];
var a_copy = a;
console.log(a === a_slice);
a_slice[0]="f";
console.log(a_slice);
console.log(a);

 var obj = {name:"xixi",age:20};
 var obj_extend = $.extend(true,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。
 console.log(obj === obj_extend);
 obj.name = "heihei";
 console.log(obj);
 console.log(obj_extend);

- 基本类型:undefined,null,布尔值(Boolean),字符串(String),数值(Number)
 - 引用类型: 统称为Object类型,细分的话,有:Object类型,Array类型,Date类型,Function类型等。
 
即
var a = “A”;
在栈内存中是这样的

即
var a = {name:“jack”};
在内存中是这样的

3、不同类型的复制方式:
var a = 1;
var b = a;
console.log(a === b);
var a = 2;
console.log(a);
console.log(b);

改变 a 变量的值,并不会影响 b 的值。
内存中是这样的:
var a = 1;

var b = a;

a = 2;

 var a = {name:”jack",age:20};
 var b = a;
 console.log(a === b);
 a.age = 30;
 console.log(a);
 console.log(b);

改变 a 变量的值,会影响 b 的值。
内存中是这样的:
var a = {name:“jack",age:20};

var b = a;

a.age = 30;

深浅拷贝 的主要区别就是:复制的是引用(地址)还是复制的是实例。
所以上面的栗子2,如何可以变成深拷贝呢?
我们可以想象出让 b 在内存中像下图这样,肯定就是深拷贝了。

那么代码上如何实现呢?
利用 递归 来实现深复制,对属性中所有引用类型的值,遍历到是基本类型的值为止。
 function deepClone(source){
   if(!source && typeof source !== 'object'){
     throw new Error('error arguments', 'shallowClone');
   }
   var targetObj = source.constructor === Array ? [] : {};
   for(var keys in source){
     if(source.hasOwnProperty(keys)){
       if(source[keys] && typeof source[keys] === 'object'){
         targetObj[keys] = source[keys].constructor === Array ? [] : {};
         targetObj[keys] = deepClone(source[keys]);    //递归
       }else{
         targetObj[keys] = source[keys];
       }
     }
   }
   return targetObj;
 }
检测一下
 var a = {name:"jack",age:20};
 var b = deepClone(a);
 console.log(a === b);
 a.age = 30;
 console.log(a);
 console.log(b);

三 、最后让我们来看看 一些 js 中的 复制方法,他们到底是深拷贝还是浅拷贝?
1、 Array 的 slice 和 concat 方法
两者都会返回一个新的数组实例。
栗子
var a = [1,2,3];
var b = a.slice(); //slice
console.log(b === a);
a[0] = 4;
console.log(a);
console.log(b);

var a = [1,2,3];
var b = a.concat(); //concat
console.log(b === a);
a[0] = 4;
console.log(a);
console.log(b);

看到结果,如果你觉得,这两个方法是深复制,那就恭喜你跳进了坑里
让咱们再看一个颠覆你观念的栗子:
var a = [[1,2,3],4,5];
var b = a.slice();
console.log(a === b);
a[0][0] = 6;
console.log(a);
console.log(b);

 var obj = {name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} };
 var obj_extend = $.extend(true,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。
 console.log(obj === obj_extend);
 obj.company.name = "ali";
 obj.name = "hei";
 console.log(obj);
 console.log(obj_extend);

浅拷贝:
 var obj = {name:"xixi",age:20};
 var obj_extend = $.extend(false,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。
 console.log(obj === obj_extend);
 obj.name = "heihei";
 console.log(obj);
 console.log(obj_extend);

咦,company 的变化 可以看出 深浅复制来(即箭头所指), 红色方框圈出的地方,怎么和上面 slice 和 concat 的情况一样?难道也是羊?
 var obj = {name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} };
 var obj_json = JSON.parse(JSON.stringify(obj));
 console.log(obj === obj_json);
 obj.company.name = "ali";
 obj.name = "hei";
 console.log(obj);
 console.log(obj_json);

 完全的 深拷贝。
 
【 js 基础 】 深浅拷贝的更多相关文章
- JS中深浅拷贝 函数封装代码
		
一.了解 基本数据类型保存在栈内存中,按值访问,引用数据类型保存在堆内存中,按址访问. 二.浅拷贝 浅拷贝只是复制了指向某个对象的指针,而不是复制对象本身,新旧对象其实是同一内存地址的数据,修改其中一 ...
 - (C#基础)深浅拷贝理解
		
一方面感觉实在无趣,不知道做什么了,纯粹来个打字练习,于是有了这个. 二方面深感自己C#基础之薄弱,于是对着园友的文章一边看,一边练习,因为很多次看了,没有多久就忘了,还有练习过程中会出现一些问题,这 ...
 - python基础--深浅拷贝copy
		
拷贝是音译的词,其实他是从copy这个英文单词音译过来的,那什么是copy? copy其实就是复制一份,也就是所谓的抄一份.深浅copy其实就是完全复制一份,和部分复制一份的意思. 1.赋值运算 l1 ...
 - JS的深浅拷贝
		
项目中根据各种需求或多或少会需要用到拷贝,通过查询整理之后今天简单的记录一下. 我们可以利用 slice.concat 返回一个新数组的特性可以实现数组的拷贝. var arr = ['a', 1, ...
 - 两行代码搞定js对象深浅拷贝
		
有一段时间没有更新博客了,忙于工作.2018年刚过去,今天来开启2018第一篇博文.好了,咱们步入正题. 先上代码 /** * 遍历对象 * 1.判断是不是原始值 * 2.判断是数组还是对象 * 3. ...
 - JS实现深浅拷贝
		
1.实现浅拷贝 // 1. ...实现 let copy1 = {...{x:1}} // 2. Object.assign实现 let copy2 = Object.assign({}, {x:1} ...
 - python基础-深浅拷贝
		
深拷贝与浅拷贝 总结: # 浅拷贝:list dict: 嵌套的可变数据类型是同一个 # 深拷贝:list dict: 嵌套的不可变数据类型彼此独立 浅拷贝 # 个人理解: # 在内存中重新创建一个空 ...
 - JS复习之深浅拷贝
		
一.复习导论(数据类型相关) 想掌握JS的深浅拷贝,首先来回顾一下JS的数据类型,JS中数据类型分为基本数据类型和引用数据类型. 基本数据类型是指存放在栈中的简单数据段,数据大小确定,内存空间大小可以 ...
 - JS--变量及深浅拷贝
		
JS变量分为基本类型和引用类型 基本类型数据包括Number, String, Boolean, Null, Undefined五种类型: 引用数据类型包括Array, Date, RegExp, F ...
 - javascript简单实现深浅拷贝
		
深浅拷贝知识在我们的日常开发中还算是用的比较多,但是之前的状态一直都是只曾听闻,未曾使用(其实用了只是自己没有意识到),所以今天来跟大家聊一聊js的深浅拷贝: 首先我们来了解一下javascript的 ...
 
随机推荐
- Html5与CSS3权威指南 百度云下载
			
Html5与CSS3权威指南 百度云下载 链接:http://pan.baidu.com/s/1hq6Dlvm 密码:php3
 - Oracle主键异常处理
			
Hibernate: insert into test1.WarnWeather (WAREA, wdate, WDAYS, WINFO, WTYPE, WNO) values (?, ?, ?, ? ...
 - Java设计模式之《外观模式》及应用场景
			
原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6484128.html 1.外观模式简介 外观模式,一般用在子系统与访问之间,用于对访问屏蔽复 ...
 - Asp.Net 常用工具类之Office-文档操作(6)
			
文档一直是老大难问题,君不知,代码用时方恨少!有一套成熟的文件帮助类能很大程度上减少寻找各种资料的时间. 记得以前做一个业务,需要导出协议,一份可编辑,一份不可编辑.那么Word和PDF是最好的选择, ...
 - JS获取网站StatusCode,若存在写入文件
			
JS获取网站状态码,若网站存在,写入TXT文件,适用于IE. <script> //写文件 function writeFile(filename,filecontent){ ...
 - ORM-Dapper学习<二>
			
Dapper的简介 Dapper是.NET下一个micro的ORM,它和Entity Framework或Nhibnate不同,属于轻量级的,并且是半自动的.Dapper只有一个代码文件,完全开源,你 ...
 - 记录Winform开发过程中遇到的情况
			
前两天开发了个Winform操作Excel和数据库的一个小程序,把Winform的一些东西又给捡了起来,当中又学到了一些新的东西,特来写出来留作纪念. 一.CSKIN美化框架的使用 刚开始做的时候,发 ...
 - 关于统一资源标志符URL的理解
			
URL由三部分构成 A:B:C A:URL使用的领域 B:在此领域的类型名称 C:标识资源的具体位置 C可以是一个绝对路径,也可以是端口号加上资源名称,总之是可以唯一标示资源的标识 例: 在网址中 S ...
 - WebX框架学习笔记之一
			
Webx是什么? Webx是一套基于Java Servlet API的通用Web框架.它在Alibaba集团内部被广泛使用.从2010年底,向社会开放源码. Webx的发展历史 2001年,阿里巴巴内 ...
 - 解决SQLServer 2008 日志无法收缩,收缩后大小不改变
			
问题 数据库日志文件上G,或者几十G了,使用日志收缩,和日志截断收缩都不管用.体积一直减不下来.. 解决方案 查看日志信息 在查询分析器中执行如下代码来查看日志信息: DBCC LOGINFO('数 ...