浅拷贝是对象的逐位复制。创建一个新对象,该对象具有原始对象中值的精确副本。如果对象的任何字段是对其他对象的引用,则只复制引用地址,即,复制内存地址。
默认情况下:引用类型(object)都是浅拷贝
简单理解:对于对象来说,就是对最外层数据的拷贝,如果对象只有一层,则相当于深拷贝,如果对象有多层,即某个属性为引用数据类型,则拷贝的是该引用类型在堆中的地址,不会在内存创建一个新的对象。
将obj1和obj2中的可枚举属性拷贝到第一个目标对象中,并且将这个对象返回
// 对象的浅拷贝
// 1.Object.assign()
let obj0={a:0}
let obj2 = Object.assign(obj0,obj1)
console.log(obj0===obj2) //true
console.log(obj1===obj2) // false
obj1.name = '张三1' //obj2不变
obj1.hobby[0]='打篮球' //obj2变了
obj1.friend.name='李四1' //obj2变了
console.log(obj1)
console.log(obj2)
// 2.展开运算符
let obj3 = {...obj1}
obj1.hobby.push('摄影') //obj3会改变
console.log(obj3)
如果被拷贝对象的属性值为简单类型(如Number,String),通过Object.assign({},Obj)得到的新对象为深拷贝;如果属性值为对象或其它引用类型,则只拷贝了该引用类型的地址。
将alpha和numeric合并为一个新数组并返回
let arr1 = ['哈哈',18,{name:'哈利',age:10}]
let arr2 = ['嘿嘿',19,{name:'赫敏',age:11}]
// 1.concat
let arr3 = arr1.concat(arr2)
console.log(arr3===arr1) //false
console.log(arr3===arr2) // false
arr1[0]='haha' //arr3不会改
arr1[2].age=100 //arr3会改
console.log(arr3)
slice()
方法返回一个新的数组对象,这一对象是一个由 begin
和 end
决定的原数组的浅拷贝(包括 begin
,不包括end
)。原始数组不会被改变。
// 1.slice截取数组
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4));
// expected output: Array ["camel", "duck"]
//2.slice浅拷贝
let arr1 = ['哈哈',18,{name:'哈利',age:10}]
let arr4 = arr1.slice() //不传参数相当于浅拷贝数组
console.log(arr4===arr1) //false
arr1[2].name = '哈利111' //arr4会变
console.log(arr4)
// 3.展开运算符
let arr1 = ['哈哈',18,{name:'哈利',age:10}]
let arr5 = [...arr1]
arr1[2].age=5 //arr5会改变
console.log(arr5)
参考:https://github.com/YvetteLau/Step-By-Step/issues/17https://github.com/YvetteLau/Step-By-Step/issues/17
封装一个函数来实现:
function isObject(value) {
const valueType = typeof value
return (value !== null) && (valueType === "object")
}
function deepClone(originValue, map = new WeakMap()) {
// 判断是否是一个Set类型
if (originValue instanceof Set) {
return new Set([...originValue])
}
// 判断是否是一个Map类型
if (originValue instanceof Map) {
return new Map([...originValue])
}
// 判断如果是Symbol的value, 那么创建一个新的Symbol
if (typeof originValue === "symbol") {
return Symbol(originValue.description)
}
// 判断如果是函数类型, 那么直接使用同一个函数
if (typeof originValue === "function") {
return originValue
}
// 判断传入的originValue是否是一个对象类型
if (!isObject(originValue)) {
return originValue
}
if (map.has(originValue)) {
return map.get(originValue)
}
// 判断传入的对象是数组, 还是对象
const newObject = Array.isArray(originValue) ? []: {}
map.set(originValue, newObject)
for (const key in originValue) {
newObject[key] = deepClone(originValue[key], map)
}
// 对Symbol的key进行特殊的处理
const symbolKeys = Object.getOwnPropertySymbols(originValue)
for (const sKey of symbolKeys) {
// const newSKey = Symbol(sKey.description)
newObject[sKey] = deepClone(originValue[sKey], map)
}
return newObject
}