说起前端的浅拷贝与深拷贝得先从javascript中的数据类型说起:
js数据类型分为俩大类:
原始数据类型:undefined null boolean number string 原始数据类型直接存储在栈(stack)中简单数据段,占据空间小,大小固定,属于被频繁使用的数据,所以存储在栈中;
引用类型数据:Object function Array 引用数据类型直接存储在堆中,占据空间大,大小不固定,如果存储在栈中,将会影响程序运行的性能,引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后,从堆中获得实体。
如下图所示
浅拷贝定义:只是把要拷贝的对象的指针拷贝了过去,并未重新开辟内存,例如 一个数组 var arr1 = ["a","b",1,2,3];var arr2 = arr1;此时arr1和arr2在内存中他们的指针都指向同一个地址,比如我进行如下操作更改arr2[0] = "A";那么arr1也会跟着响应的改变,此时arr1 变为了 ["A","b",1,2,3],因为arr2只是拷贝了arr1指向真正存放arr1数组在内存中的指针,arr1和arr2俩个数组对象指向的内存地址是同一个,并没有复制引用类型的数据,所以arr2修改了数组元素,arr1也会跟着改变。
深拷贝定义:在javascript中数据类型分为基本数据类型/引用数据类型,基本数据类型相对于来说,所有的拷贝都是深拷贝,因为只要我们定义一个基础数据类型,那么系统就会开辟一段地址用于存放基础数据类型,ES6中的symbol()也适用 var a = Symbol(12),b = a;。b = symbol(2);此时a依然是symbol(12);
实现浅拷贝的方法
1.利用es6 Obect.assign()实现浅拷贝
var obj = {name:"lily",age:18};
var copy_obj = Object.assign({},obj) // {name: "lily", age: 18}
2.直接引用赋值
var arr1 = ["a","b",1,2,3];var arr2 = arr1
3.$.extend( [deep ], target, object1 [, objectN ] )jquery实现浅拷贝
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
targetObject类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。
var obj1 = {name:"lily"};
var obj2 = {age:16};
var obj3 = {sex:male};
var objnew = $.extend(false,{},obj1,obj2,obj13)
实现深拷贝的方法
1.$.extend( [deep ], target, object1 [, objectN ] )jquery实现浅拷贝
第一个参数改为true可以实现深拷贝
2.递归实现深拷贝
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
} 3.可以借用JSON对象的parse和stringify
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
没法复制函数,正则,symbol
总结:深拷贝会重新开辟内存地址,浅拷贝只是拷贝了对象的指针。