【 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 基础 】【 源码学习 】 深浅拷贝的更多相关文章
- Vue.js 源码学习笔记
最近饶有兴致的又把最新版 Vue.js 的源码学习了一下,觉得真心不错,个人觉得 Vue.js 的代码非常之优雅而且精辟,作者本身可能无 (bu) 意 (xie) 提及这些.那么,就让我来吧:) 程序 ...
- 【目录】Spring 源码学习
[目录]Spring 源码学习 jwfy 关注 2018.01.31 19:57* 字数 896 阅读 152评论 0喜欢 9 用来记录自己学习spring源码的一些心得和体会以及相关功能的实现原理, ...
- 【 js 基础 】【 源码学习 】源码设计 (持续更新)
学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...
- 【 js 基础 】【 源码学习 】backbone 源码阅读(一)
最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...
- 【 js 基础 】【 源码学习 】backbone 源码阅读(二)
最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(source-code-study)进行参考交流,有详细的源码注释,以及知识总结,同时 ...
- 【 js 基础 】【 源码学习 】backbone 源码阅读(三)浅谈 REST 和 CRUD
最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...
- 【 js 基础 】【 源码学习 】backbone 源码阅读(三)
最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...
- 【 js 基础 】【 源码学习 】源码设计 (更新了backbone分析)
学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析 第二部分:unders ...
- Underscore.js 源码学习笔记(下)
上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...
- Underscore.js 源码学习笔记(上)
版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}()); 这样的东西,我们应该知道这是一个 IIFE(立即执行 ...
随机推荐
- 定位 和 z-index
三.定位 定位有三种:(1) 相对定位.(2) 绝对定位.(3) 固定定位 1.相对定位(相对于自己原来的位置定位) 现象和使用: a.如果对当前元素仅仅设置了相对定位,那么与标准流的盒子没什么区别: ...
- Data - 数据思维
数据思维 数据思维全解析 如何建立数据分析的思维框架 做数据分析时,你的方法论是什么? 数据分析全流程资料,适合各路人马 百度内部培训资料PPT:数据分析的道与术 学会数据分析背后的挖掘思维,分析就完 ...
- Ubuntu14.04 + Text-Detection-with-FRCN(CPU)
操作系统: yt@yt-MS-:~$ cat /etc/issue Ubuntu LTS \n \l Python版本: yt@yt-MS-:~$ python --version Python pi ...
- oracle 闪回、归档的设置建议
闪回与归档的相关测试 参考博客:http://www.cnblogs.com/hellojesson/p/7050097.html 数据库在归档模式下的管理 参考博客:http://www.cnblo ...
- 课程一(Neural Networks and Deep Learning)总结——1、Logistic Regression
---------------------------------------------------------------------------------------------------- ...
- IdentityServer4之Clients、Scopes、Claims与Token关联
IdentityServer4之Clients.Scopes.Claims与Token关联 参考 官方文档:client.identity_resource.api_resource:三类配置项介绍描 ...
- 微信 JS-SDK 签名验证
doc: http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html demo:http://demo.open.weix ...
- Android_ 重写系统Crash处理类,保存Crash信息到SD卡 和 完美退出程序的方法
转载时注明地址:http://blog.csdn.net/xiaanming/article/details/9344703 我们开发Android应用的时候,当出现Crash的时候,系统弹出一个警告 ...
- 第一章-Javac编译器介绍
1.Javac概述 编译器可以将编程语言的代码转换为其他形式,如Javac,将Java语言转换为虚拟机能够识别的.class文件形式.而这种将java源代码(以.java做为文件存储格式)转换为cla ...
- Spring事务内方法调用自身事务 增强的三种方式
ServiceA.java文件: 查看Spring Tx的相关日志: 可以看到只创建了一个事物ServiceA.service方法的事务,但是callSelf方法却没有被事务增强; 分析原因:Spr ...