理解js中的浅拷贝和深拷贝
2019-09-25 本文已影响0人
不懂代码的小白
JavaScript的变量类型
- Number Boolean String Null undefined Object Function
基本类型
- Number Boolean String undefined null
- 变量是直接按值存放的,存放在栈内存中的简单数据段,可以直接访问。
引用类型
- Object Function
- 存放在堆内存中的对象,变量保存的是一个指针,这个指针指向另一个位置。当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。
浅拷贝
- 复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变。
深拷贝
- 重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型。两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
浅拷贝和深拷贝的区别
- 浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用。
- 深拷贝是拷贝多层,递归复制了所有层级。
浅拷贝实现
Object.assign()
- 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
let obj1 = {
name: '张三',
age: 18,
child: {
name: '李四',
age: 22
}
}
let obj2 = Object.assign({}, obj1)
obj2.age = 50
obj2.child.age = 888
console.log(obj1)
console.log(obj2)
$ node index.js
{ name: '张三', age: 18, child: { name: '李四', age: 888 } }
{ name: '张三', age: 50, child: { name: '李四', age: 888 } }
自定义方法 shadowCopy()
- 实现简单的引用复制
function shadowCopy(obj) {
let newObj = {}
for (let k in obj) {
newObj[k] = obj[k]
}
return newObj
}
let obj1 = {
name: '张三',
age: 18,
child: {
name: '李四',
age: 22
}
}
let obj2 = shadowCopy(obj1)
obj2.age = 50
obj2.child.age = 888
console.log(obj1)
console.log(obj2)
$ node index.js
{ name: '张三', age: 18, child: { name: '李四', age: 888 } }
{ name: '张三', age: 50, child: { name: '李四', age: 888 } }
深拷贝实现
JSON.paerse() JSON.stringify()
- 用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。
缺点
-
会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
-
能正确处理的对象只有 Number String Boolean Array 扁平对象,即那些能够被 json 直接表示的数据结构。
-
RegExp对象是无法通过这种方式深拷贝。
-
只有可以转成JSON格式的对象才可以这样用,function没办法转成JSON。复制后生成的对象的function属性会直接消失,这个方法只能用在单纯只有数据的对象。
let obj1 = {
name: '张三',
age: 18,
child: {
name: '李四',
age: 22
},
func() {
console.log('hello:' + this.name)
}
}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.age = 50
obj2.child.age = 888
console.log(obj1)
console.log(obj1.func)
console.log('------------------------')
console.log(obj2)
console.log(obj2.func)
$ node index.js
{ name: '张三',
age: 18,
child: { name: '李四', age: 22 },
func: [Function: func] }
[Function: func]
------------------------
{ name: '张三', age: 50, child: { name: '李四', age: 888 } }
undefined
自定义方法 deepCopy()
function deepCopy(obj) {
let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object' && obj[key]!==null) {
result[key] = deepCopy(obj[key]); //递归复制
} else {
result[key] = obj[key];
}
}
}
return result;
}
let obj1 = {
name: '张三',
age: 18,
child: {
name: '李四',
age: 22
},
func() {
console.log('hello:' + this.name)
}
}
let obj2 = deepCopy(obj1)
obj2.name = '陈二'
obj2.age = 50
obj2.child.name = 'bgbhjbj'
obj2.child.age = 888
console.log(obj1)
console.log(obj1.func)
console.log('------------------------')
console.log(obj2)
console.log(obj2.func)
$ node index.js
{ name: '张三',
age: 18,
child: { name: '李四', age: 22 },
func: [Function: func] }
[Function: func]
------------------------
{ name: '陈二',
age: 50,
child: { name: 'bgbhjbj', age: 888 },
func: [Function: func] }
[Function: func]