目录
深浅拷贝
学go语言毁了我。。。js的深浅拷贝和go不一样,以为是我学糊涂了原来真的不一样哈。。。
首先我们回顾一下值类型和引用类型:
类型 | 描述 | 示例 |
---|---|---|
值类型 | 直接存储值,赋值时会复制值本身。 | let a = 10; let b = a; (修改 b 不会影响 a ) |
引用类型 | 存储的是内存地址,赋值时复制的是引用(内存地址)。 | let a = { name: 'Alice' }; let b = a; (修改 b 会影响 a ) |
然后再聊一下什么是赋值:
赋值是将一个变量的引用(内存地址)复制给另一个变量。两个变量会指向同一个内存地址;就像这样:
修改其中一个的属性值,另一个也跟着改变,因为他们的内存地址相同
所以为了避免这种情况,在js里给对象、数组这种引用类型使用了深浅拷贝
在js里数组和对象等都为引用类型,而深浅拷贝只适用于引用类型的数据,在值类型的数据里不作深浅拷贝的区分
浅拷贝
拷贝的是地址
在js里实现浅拷贝:通过展开运算符
const obj = {
uname: '荷叶饭',
age: 18,
}
const o = { ...obj }
o.age = 20
console.log(o)
console.log(obj)
这样就实现了对象的浅拷贝
Object.assign()也可以
Object.assign()
静态方法将一个或者多个源对象中所有可枚举的自有属性复制到目标对象,并返回修改后的目标对象。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target);
// Expected output: true
但是这样会出现这样一种问题:当对象嵌套的时候
const obj = {
uname: '荷叶饭',
age: 18,
friends: {
EPI: '励志轩'
}
}
const o = {}
Object.assign(o, obj)
o.age = 20
o.friends.EPI = '荷月'
console.log(o)
console.log(obj)
按理来说friends内被修改的应该是独立的,怎么o已修改obj也跟着改了?
孩子们这就是浅拷贝,浅拷贝真的很浅,只拷贝了最外面的一层
第一层独立:修改第一层属性不会影响原对象。
嵌套层共享:里面的属性值是简单数据类型直接拷贝值;如果属性是引用类型(如对象、数组),修改嵌套层会影响原对象,拷贝的是地址
深拷贝
深拷贝是创建一个新对象,并递归复制原对象的所有层级属性,新对象和原对象完全独立。
函数递归
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
递归要素:边界条件+递归方程,再达到边界条件的时候return,因为递归很容易发生“栈溢出”错误(stack overflow)
之前说过setTimeout可以用递归模拟setInterval,来试试看:
function getTime() {
document.querySelector('div').innerHTML = new Date().toLocaleString()
setTimeout(getTime,1000)
}
getTime()
递归如何解决深拷贝呢:
const obj = {
uname: '荷叶饭',
age: 18,
friends: {
EPI: '励志轩'
},
hobby: ['乒乓球', '羽毛球']
}
const o = {}
function deepCopy(newObj, oldObj) {
for (let k in oldObj) {
if (oldObj[k] instanceof Array) {
//如果是数组
//数组本身也属于对象,所以一定把筛选数组的if写在前面
newObj[k] = []
deepCopy(newObj[k], oldObj[k])
} else if (oldObj[k] instanceof Object) {
//如果是对象
newObj[k] = []
deepCopy(newObj[k], oldObj[k])
} else {
//值类型情况
newObj[k] =