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),一般存放于内存 ...
随机推荐
- Tomcat8配置默认项目
<!-- 配置默认访问项目 --> <Host name="localhost" appBase="webapps" unpackWARs=& ...
- MSF爆破MSSQL
show options: msf auxiliary(scanner/mssql/mssql_login) > show options Module options (auxiliary/s ...
- MongoDB的安装配置、基本操作及Perl操作MongoDB
MongoDB的安装配置.基本操作及Perl操作MongoDB http://www.myhack58.com/Article/60/63/2014/42353.htm
- zip函数的应用
#!/usr/bin/env python # encoding: utf-8 from itertools import zip_longest # ➍ # zip并行从输入的各个可迭代对象中获取元 ...
- STL之顺序容器 deque 动态数组
deque是一个动态数组,deque与vector非常类似,vector是一个单向开口的连续线性空间,deque则是双向开口的连续线性空间.两者唯一的区别是deque可以在数组的开头和末尾插入和删除数 ...
- .NET Core、.NET Standard、Xamarin和.NET Framework对比
近日,微软发布了.NET Core 2.0,但是开发人员中间仍然存在一些疑惑,就是.NET Core..NET Standard.Xamarin和.NET Framework有什么不同. .NET F ...
- ReentrantLock 分析
带着疑问去分析 ReentrantLock是如何实现锁管理的. ReentrantLock是如何实现重入的. ReentrantLock是如何实现公平锁与非公平锁. ReentantLock的公平锁为 ...
- hdu 3667(最小费用最大流+拆边)
Transportation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu 3081(二分+并查集+最大流||二分图匹配)
Marriage Match II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- hdu 1428(很好的一道题,最短路+记忆化搜索)
漫步校园 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...