浅拷贝
1. Object.assign(target, source) 将多个源对象中的属性复制到一个目标对象中
//例如1:
let obj1 = {
person:{
name: 'kobe', age:18
},
sports: 'basketball'
}
let obj2 = Object.assign({}, obj1)
obj2.person.name = 'wade'
obj2.sports = 'football'
console.log(obj1)// { person:{ name: 'wade', age:18 }, sports: 'football'}
//例如2
const source1 = {
a: 123,
b: 123
}
const source2 = {
b: 789,
d: 789
}
const target = {
b: 456,
c: 456
}
// 参数1:将属性复制到的目标对象;参数2:复制的源对象
// 将source1中的属性和值 复制(覆盖)到target中, 有重复到会被覆盖源对象覆盖
// const res1 = Object.assign(target, source1)
// console.log(res1)//{b: 123, c: 456, a: 123}
// console.log(res1 === target) //true
const res2 = Object.assign(target, source1, source2)
console.log(res2)//{b: 789, c: 456, a: 123, d: 789}
console.log(res2 === target) //true
2.展开运算符 …
let obj1 = {
name: 'kobe',
address:{ x:100 }
}
let obj2 = {...obj1}
obj1.name = 'wade'
obj1.address.x = 200
console.log(obj2)// { name: 'wade', address:{ x:200 } }
3.数组concat() 方法
let arr = [1,3, { name: 'kobe'}]
let arr2 = arr.concat()
arr2[2].name = 'wade'
console.log(arr,arr2)//[1,3, { name: 'wade'}]
4.数组slice() 方法
let arr = [1,3, { name: 'kobe'}]
let arr2 = arr.slice()
arr2[2].name = 'wade'
console.log(arr2)//[1,3, { name: 'wade'}]
深拷贝
1.JSON.parse(JSON.stringify(obj))
满足一般使用场景,但无法实现对象中方法(fountion)的深拷贝
let obj = {
id: 1,
name: '张三',
age: 10,
}
let newObj = JSON.parse(JSON.stringify(obj))
(1)如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式
(2)如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
(3)如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
(4)如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
(5)JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
(6)如果对象中存在循环引用的情况也无法正确实现深拷贝;
2.递归拷贝
递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。
比较全面的深拷贝,缺点是较为繁琐
function deepClone(obj) {
var target = {};
for(var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (typeof obj[key] === 'object') {
target[key] = deepClone(obj[key]);
} else {
target[key] = obj[key];
}
}
}
return target;
}
3.jQuery的extend方法实现深拷贝
jQuery.extend() 函数用于将一个或多个对象的内容合并到目标对象。
第一个参数是boolean类型,表示深浅拷贝,true表示深拷贝,false表示浅拷贝。只有两个参数,那么就把jQuery作为target,把第二个参数的字段赋给target,然后返回target。多于两个参数,把第二个参数作为target,然后把后面的参数的字段赋给target,最后面返回target.
var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝
let obj = {
a:1,
b: {
c:2
}
}
let copyObj = {}
$.extend(true,copyObj, obj);
copyObj.b = 3
console.log(obj, copyObj)
问题:当然如果两拷贝对象中有相同的属性名时,后者的值也会覆盖前者的值,就像这样:
let obj = {
a:1,
b: {
c:2
}
}
let obj2 = {
a:2,
d:4
}
$.extend(true,obj, obj2);
console.log(obj, obj2)
jQuery这个框架现在使用量比较小,个人不做深入研究了
4.Object.assign(obj1, obj2)---伪
只有一级属性为深拷贝,二级属性后就是浅拷贝
let obj = {
id: 1,
name: '张三',
age: 10,
}
let newObj = Object.assign({}, obj)
5.扩展运算符---伪
只有一级属性为深拷贝,二级属性后就是浅拷贝
var obj = {
a: 1,
b: 2
}
var obj1 = {...obj}
6.数组使用数组方法进行深拷贝(concat、slice)---伪
只有一级属性为深拷贝,二级属性后就是浅拷贝,如数组中的对象
var arr1 = [1, 2, 3, 4]
var arr2 = arr1.concat()
var arr3 = arr1.slice(1)