hello,我是泰戈尔,今天给大家讲讲深拷贝及浅拷贝的原理
如果要理解前端的深拷贝和浅拷贝,首先要了解什么是简单数据类型和引用(复杂)数据类型,
简单数据类型:
1. Number(数字)
2. String(字符串)
3. Boolean(布尔)
4. undefined(声明未定义)
5. null(未赋值)
复杂数据类型:
1. Object
2. Array
3. Function
4. Math
5. Date等等....
首先什么是拷贝,
拷贝就是将一个对象obj1
复制给另一个对象obj2
,且当obj2
的数据发生改变时,obj1
不会被改变
什么是浅拷贝:
# 浅拷贝就是只拷贝对象的一层属性,如果对象里面还有对象,拷贝的是内存地址,并且此时修改数据会对原对象有影响,浅拷贝适用于对象属性里面的值是简单数据类型的
简单数据类型
var a = 1,//这里声明a = 1 ,此时已经写入栈内存中,
var b = a,//然后声明b = a,此时将a的值给b,那么b的值也会在栈内存中开辟一个空间,
var a = 2,//如果此时我们将a的值修改,看b的值会不会跟着变。
console.log(b),//可以看见此时b的值并没有改变。
复杂数据类型
var arrayA = [1,2,3,4,5], //这里是一个复杂的数据类型Array
var arrayB = arrayA, //这里直接将原数组的值给新数组,
arrayA[0] =1, //这里修改原数组的第一项的值,会发现新数组的值也会跟着变。
console.log(arrayB),//新数组会跟着变,是因为复杂数据类型的值会放在堆内存中,变量名会放在栈内存中,
但是栈内存会提供一个地址指向堆内存中对应的值,所以在进行对原复杂数据类型进行copy操作时,
只是复制引用同一个内存地址而已,并没有拿到其内存地址指向的值,
所以在进行修改操作时,修改原数组的值,新数组的值也会跟着改变了。
用代码演示并实现浅拷贝:
# 利用for in方法遍历原对象,声明一个新对象,然后使新对象的对应索引的值等于原对象对应索引的值,最后返回这个新对象,
var obj = {
class: 'UI',
age: 20,
love: 'eat'
}
function getObj(obj) {
var newObj = {}
for (var k in obj) {
newObj[k] = obj[k]
}
return newObj
}
var obj2 = getObj(obj)
# 只拷贝一层属性的时候,修改数据不会影响原对象内部的数据,
# 如果拷贝的是对象内部的对象的时候,此时修改其数据,会改变原对象的内部的对象的数据,
什么是深拷贝:
# 深拷贝就是拷贝对象的多层属性,如果对象里面还有对象,会继续拷贝,此时修改其数据不会改变原对象内部的数据,主要使用递归函数去实现.
用代码演示并实现深拷贝:
# 创建一个新对象,利用for in方法,遍历原对象,使原对象对应索引的值等于新创建的对象索引的值,使用 typeof 方法判断对象内部是否全部为简单的数据类型,如果是则直接返回这个对象,如果对象内部还有对象(就是返回值是object的话,则继续遍历,直到对象内部没有对象为止,)
var obj = {
class: '前端',
age: 26,
love: {
friuts : 'apple',
meat: 'beef'
}
}
function getObj(obj) {
var newObj = {}
for (var k in obj) {
newObj[k] = typeof obj[k] == 'object' ? getObj(obj[k]) : obj[k]
}
return newObj
}
var obj2 = getObj(obj)
# 最后可以使用三元表达式对代码进行精简优化
好了到此就讲完了深拷贝和浅拷贝的原理,前端深似海,学习不止步,加油!