JavaScript的深拷贝与浅拷贝
深拷贝和浅拷贝是在面试中经常遇到的问题。今天在这里总结一下。
深拷贝与浅拷贝的问题,涉及到JavaScript的变量类型,先来说说变量的类型,变量类型包括基本类型和引用类型。
- 基本类型:Undefined,Null,Boolean,String,Number
- 引用类型:Array,Object,Date,RegExp,Function等
基本类型的变量直接按值存放在栈区里面,可以直接访问,比如我们平时把字符串、数字的值赋值给新变量,就是把值完全赋值过去,新变量的改变不会影响旧变量。
引用类型是存放在堆区的对象,变量在栈区中保存的是一个指针地址,指向真正保存在堆区中的对象。
浅拷贝
1.定义:浅复制只复制一层对象的属性。
- 针对对象中的基本类型是新开辟一块内存进行存储,改变新对象中的基本类型值不会影响原对象。
- 而对于对象中的引用类型,也会新开辟一块内存,不过这块内存,仅仅是用来存储对象中的引用类型的地址(即指针,这个指针还是指向存储在堆内存中的原对象)
先来看一段代码:下面这段代码只是浅复制
var obj = {
a:1,
arr: [2,3]
};
var shallowObj = shallowCopy(obj);
function shallowCopy(src){
var dst = {};
for(var prop in src){
if(src.hasOwnProperty(prop)){
dst[prop] = src[prop];
}
}
return dst;
}
console.log(shallowObj.a);//1
shallowObj.a = 3;
console.log(shallowObj.a);//3
console.log(obj.a);//1
console.log(shallowObj.arr);//[2,3]
shallowObj.arr[0] = 3;
console.log(shallowObj.arr);//[3,3]
console.log(obj.arr);//[3,3]

2.实现方式
- 可以通过es6新增的Object.assign来复制对象
let obj = {
name: "xiaoming",
hobby: [
"pinpong",
"soccer"
]
};
let copyObj = Object.assign({},obj);
copyObj.name = "xiaohong",
copyObj.hobby[0] = "jianzi";
console.log(obj);
console.log(copyObj);

- jQuery中的$.extend(,obj);Array.prototype.slice()和Array.prototype.concat()都会返回一个数组或者对象的浅拷贝。
深拷贝
1.定义:深拷贝不仅会将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上,这就不会存在上图中的obj和shallowObj的arr属性指向同一个对象的问题。
function cloneDeep(obj){
if(typeof obj !== 'object' || Object.keys(obj).length === 0 ){
return obj;
}
let resultData = {};
return recurison(obj, resultData);
}
function recurison(obj, data = {}){
for(key in obj){
if(typeof obj[key] == 'object' && Object.keys(obj[key].length > 0 )){
data[key] = recurison(obj[key]);
}else{
data[key] = obj[key];
}
}
return data;
}
var o1 = {
arr: [1, 2, 3],
obj: {
key: 'value'
},
func: function(){
return 1;
}
};
var o3 = cloneDeep(o1);
console.log(o3 === o1);//false
console.log(o3.obj === 01.obj);//false
console.log(o3.func === o1.func);//true

深拷贝对基本类型和引用类型都会新开辟一块内存来存储它们,需要注意的是,如果对象比较大,层级比较多,深复制会带来性能上的问题。所以在遇到深复制的情况时,可以考虑有没有其他替代的方案。在实际的应用场景中,也是浅复制更为常用。
2.JSON对象中的parse和stringify,JSON对象中的stringify可以把一个js对象序列化为一个JSON字符串,parse可以将JSON字符串反序列化为一个js对象,通过这两个方法,也可以实现对对象的深复制。
JavaScript的深拷贝与浅拷贝的更多相关文章
- javascript对象深拷贝,浅拷贝 ,支持数组
javascript对象深拷贝,浅拷贝 ,支持数组 经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One meth ...
- 也来玩玩 javascript对象深拷贝,浅拷贝
经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...
- JavaScript的深拷贝和浅拷贝总结
深拷贝和浅拷贝 深拷贝:拷贝实例:浅拷贝:拷贝引用(原对象). 说深拷贝和浅拷贝之前,我先去了解了下高程书上的JavaScript的变量类型: 基本类型:undefined.null.Boolean. ...
- JavaScript的深拷贝和浅拷贝
一.数据类型 数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型.. 1.基本数据类型的特点:直接存储在栈(stack ...
- 详解javascript的深拷贝与浅拷贝
1. 认识深拷贝和浅拷贝 javascript中一般有按值传递和按引用传递两种复制,按值传递的是基本数据类型(Number,String,Boolean,Null,Undefined),一般存放于内存 ...
- JavaScript 的 深拷贝和浅拷贝
深拷贝和浅拷贝都是针对的引用类型, JS中的变量类型分为值类型(基本类型)和引用类型: 对值类型进行复制操作会对值进行一份拷贝,而对引用类型赋值,则会对地址进行拷贝,最终两个变量指向同一份数据 一.先 ...
- JavaScript之深拷贝和浅拷贝
前言 工作中会经常遇到操作数组.对象的情况,你肯定会将原数组.对象进行‘备份’当真正对其操作时发现备份的也发生改变,此时你一脸懵逼,到时是为啥,不是已经备份了么,怎么备份的数组.对象也会发生变化.如果 ...
- javaScript深拷贝和浅拷贝简单梳理
在了解深拷贝和浅拷贝之前,我们先梳理一下: JavaScript中,分为基本数据类型(原始值)和复杂类型(对象),同时它们各自的数据类型细分下又有好几种数据类型 基本数据类型 数字Number 字符串 ...
- 读懂javascript深拷贝与浅拷贝
1. 认识深拷贝和浅拷贝 javascript中一般有按值传递和按引用传递两种复制,按值传递的是基本数据类型(Number,String,Boolean,Null,Undefined),一般存放于内存 ...
随机推荐
- android CVE 漏洞汇总
arm exploits 技术教程: Learning Pentesting for Android Devices CVE-2015-1530 ,CVE-2015-1474 两个android整数溢 ...
- Linux(Unix)密码策略问题导致root密码不能修改
Linux(Unix)密码策略问题导致root密码不能修改 发布时间: 2016-01-19 浏览次数: 1034 下载次数: 5 用户修改了密码配置文件,导致root账户修改密码时报如下错误: ...
- linux 下多版本gcc 共存问题
linux 下多版本gcc 共存问题 http://blog.csdn.net/isfirst/article/details/42296583 参考 http://blog.csdn.net/chi ...
- 安装openssl-0.9.8报错out range of signed 32bit displacement .
安装openssl-0.9.8报错out range of signed 32bit displacement http://blog.csdn.net/wangtingyao1990/article ...
- 利用keepalive+mysql replication 实现数据库的高可用
利用keepalive+mysql replication 实现数据库的高可用 http://www.xuchanggang.cn/archives/866.html
- c++ 引用的分析
在一般教材里面,我们会说引用是变量的别名,另外在 c++ primer 5里面说到引用的时候,说引用不是对象,不能对它进行取地址.但是我们来看看下面代码的分析: #include <iostre ...
- 【linux】su和sudo命令的区别
来源:http://www.jb51.net/LINUXjishu/12713.html 一. 使用 su 命令临时切换用户身份 1.su 的适用条件和威力 su命令就是切换用户的工具,怎么理解呢?比 ...
- Django 1.6在Windows平台下的配置
Django 1.6 在Windows平台下的配置 前言 最近两天研究了下Django1.6在Windows平台中的配置安装,服务器采用Apache.期间遇到过许多新手所遇到的各种问题,也算是一种宝贵 ...
- windows网卡命令
netsh interface ip set address name="本地连接" source=dhcpnetsh interface ip set dns name=&quo ...
- golang实现mysql数据库备份
背景 navicat是mysql可视化工具中最棒的,但是,在处理视图的导入导出方面,它是按照视图名称的字母顺序来处理的,若视图存在依赖,在导入过程中就会报错.前面已经用python写了一个,但在使用过 ...