【 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的 ...
随机推荐
- React Native与原生项目连接与发布
前面的各种环境配置按照官方文档一步一步来,挺详细,宝宝在这里就不多说废话了. 其次,前面的配置,我参照的这个博主的文章React Native 集成到iOS原生项目 下面是宝宝掉过的坑(半径15M): ...
- Hibernate执行流程和关系映射
一.Hibernate的执行流程 hibernate作为一个ORM框架,它封装了大量数据库底层的sql语句操作的方法,这样在执行hibernate的过程中理解hibernate的执行流程很有必要. 由 ...
- PDO数据访问抽象层
PDO数据访问抽象层: 我们使用的mysqli是针对mysql这个数据库扩展的一个类,如果要用到别的数据库的话就可以用PDO来做 1.操作数据库 先来代码 <!--PDO--> <! ...
- mfc--使用ShellExecute打开另一个可执行程序
ShellExecute(sFile [, vArguments] [, vDirectory] [, vOperation] [, vShow]) ShellExecute(NULL,"o ...
- linux 之 tcpdump
tcpdump详细命令 -i 参数指定监听网口 -c 参数指定监听的数据包数量 -s 参数指定监听数据包大小 -w 参数指定监听数据包写入文件 如果要监听某几台主机数据包 例如10.10.10.10. ...
- 数字化工厂ERP解决方案
数字化工厂 数字化工厂建设,在现有基础上提升,实现管理层对订单进度.生产绩效.产能分析.质量管理.产品追溯和存货管理等提供业务分析报告:在控制层有可视化看板.移动客户端实现对生产状态的实时掌控,快速处 ...
- 怎么用php语言来做文件缓存
使用缓存能够让我们的程序访问起来更加快速,缓存可以减少对数据库的操作,体验起来更好一些,对服务器的压力也小一些,当然服务速度很快 php文件执行完之后产生的解析完的数据,保存成静态的网页,下次打开的这 ...
- java如何在一个范围内产生多个不等的随机数
import java.util.Random; //随机产生0-max之间num个不重复的整数 public class 产生多个不同随机数 { private static int num,max ...
- ajax三级联动下拉菜单
ajax写三级联动,先写一个文件类吧,以后用的时候直接调用即可: 来找一张表: 实现: 中国地域的三级联动:省.市.区: 图: 说一下思路: (1)当用户选择省份的时候触发事件,把当前的省份的id通过 ...
- Servlet 3.0/3.1 中的异步处理
在Servlet 3.0之前,Servlet采用Thread-Per-Request的方式处理请求,即每一次Http请求都由某一个线程从头到尾负责处理.如果一个请求需要进行IO操作,比如访问数据库.调 ...