一、概念区分:
- 赋值:obj2 = obj1 ,实际上是将Obj2变量指向和obj1变量同一个在栈中的地址,赋值后两个对象指向的是同一个存储空间。
- 浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。
- 深拷贝:重新在堆中创建内存,对象中的子元素进行递归拷贝,拷贝前后的两个对象进行修改值时互不影响。
**以下均为拷贝对象不止一级的情况
二、浅拷贝实现方式:
- Object.assign()
- Object.create()
- lodash 里的 _.clone
- { …obj } 展开运算符
- Array.prototype.concat
- Array.prototype.slice
三、深拷贝实现方式
- lodash 里的 _.cloneDeep
- jqeury里的 $.extend *注1
- JSON.parse(Json.stringfy(obj)) *注2
四、对象的浅拷贝方法实现
function shallowCopy(obj){
let target = {};
for(item in obj){
if(obj.hasOwnProperty(item)){
target[item] = obj[item] //赋值,引用数据类型指向同一地址
}
}
return target
}
四、对象的深拷贝方法实现
function deepClone(obj){
let cloneObj = {};
//javaScript 历史遗留问题 typeof null ==> 'object'
if(obj === null) return obj;
//如果obj是Date类型 或 RegEp类型 返回值
if(obj instanceof Date) return new Date(obj); //*注3
if(obj instanceof RegExp) return new RegExp(obj);
//如果obj不是对象,而是普通数据类型 直接返回
if(typeof obj !== 'object') return obj;
for(item in obj){
if(obj.hasOwnProperty(item)){
target[item] = deepClone(obj[item]) //赋值,引用数据类型指向同一地址
}
}
return cloneObj;
}
五、注
$.extend( target [, object1 ] [, objectN ] )
//指示是否深度合并
$.extend( [deep ], target, object1 [, objectN ] )
//警告: 不支持第一个参数传递 false 。
$.extend深度合并实例:
var result = $.extend(
true,
{},
{ name: "John", location: { city: "Boston", county: "USA" } },
{ last: "Resig", location: { state: "MA", county: "China" } }
);
console.log(result);
//{
//last: "Resig"
//location: {city: "Boston", county: "China", state: "MA"}
//name: "John"
//}
- .[转自博客] JSON.parse(JSON.stringify(obj)) 不仅能复制数组还可以复制对象,但是几个弊端:
1)它会抛弃对象的 constructor,深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成 Object;
2)这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp 对象是无法通过这种方式深拷贝。
3)只有可以转成 JSON 格式的对象才可以这样用,像 function 没办法转成 JSON。 - A instanceof B : B的原型对象prototype是否在A的原型链上