javascript 深浅拷贝
拷贝 = 复制
内容(javascript
对象)
// 如:
let obj1 = {
name:"jack",
age:18,
fun:{
swimimg:'游泳'
}
}
// 新对象
let obj2 = {
name:"jack",
age:18,
fun:{
swimimg:'游泳'
}
}
分类
浅拷贝(只拷贝一层对象) 深拷贝(可以拷贝嵌套对象)
拷贝的实现方式
- 赋值式不是拷贝(let newObj = obj )
只是给源对象重新定义了一个类名,将堆区域的地址赋给了它,两个类名都可以通过点语句修改和操作对象里定义的属性值,而不是拷贝了一个新对象。
<script>
// 要拷贝的对象
let obj = {
name:"jack",
age:18
}
let newObj = obj
consol.log("newObj",newObj ) // newObj:{name:"jack",age:18}
</script>
- JSON.parse(JSON.stringify(obj))(JONS是深拷贝)
可以拷贝一个新对象,重新在堆区域里面创建了一个储存地址,在新对象里修改对象里的属性值不会影响原来的对象,并且是完全拷贝(可以拷贝嵌套的对象),但不能拷贝Function函数
和值是undefind的属性
<script>
// 要拷贝的对象
let obj = {
name:"jack",
age:18,
say:function(){ // 该方法不能拷贝函数
consol.log("say>>>>>")
},
null:undefind, // 该方法不能拷贝值为undefind的属性
fun:{
swimming:"游泳"
}
}
/*
* 实现方式:JSON.parse(JSON.stringify(obj))
*/
// 拷贝obj对象
let newObj = JSON.parse(JSON.stringify(obj))
consol.log("拷贝后的对象newObj",newObj ) // newObj:{name:"jack",age:18,fun{swimming:"游泳"}}
</script>
- 扩展运算符(展开运算符是浅拷贝) {. . .obj} <==> object.assign(obj)
只能拷贝一层,不能拷贝嵌套对象,可以拷贝函数function和
值是undefind的属性
// 要拷贝的对象
let obj = {
name:"jack",
age:18,
say:function(){
consol.log("say>>>>>")
},
null:undefind,
fun:{ // 不能拷贝嵌套对象
swimming:"游泳"
}
}
/*
* 实现方式:{...obj}
*/
// 拷贝obj对象
let newObj = {...obj}
consol.log("拷贝后的对象newObj",newObj ) // newObj:{name:"jack",age:18,say:function(){ consol.log("say>>>>>")}, null:undefind}
</script>
- 递归拷贝
1.有嵌套对象
2.有函数function和undefind
<script>
// 深拷贝 递归实现
const cloneDeep = data => {
const newData = Array.isArray(data) ? [] : {}
for (let key in data) {
if(data[key] && typeof data[key] === 'object') {
nawData[key] = cloneDeep(data[key])
} else {
newData[key] = data[key]
}
}
return newData
}
</script>
- 优化:根据实际情况完成不同的拷贝,先封装两个判断条件
类型判断:object.prototype.toString.coll(num)
[object String] [object Object ] [object Array] [object Function]
// 判断对象属性值是否有对象,就是对象是否有嵌套对象
const isObjectValue = data => {
for (let key in data) {
if(data[key] && typeof data[key] === 'object') {
if(object.prototype.toString.call(data[key]) !== '[object function]'){
return true
}
}
}
}
// 递归判断数据类型
const isFunctionUndefined = data=> {
for (let key in data) {
if(data[key] === undefined) {
return true
} else if (data[key] && object.prototype.toString.coll(data[key]) === '[object Function]'){
return true // Function
} else if (data[key] && typeof data[key] === 'object') {
isFunctionUndefined(data[key])
}
}
}
// 使用递归方法拷贝对象
const cloneDeepObj = obj => {
if(obj === undefined) {
throm new TypeError('param is not undefined')
}
// 判断拷贝对象只有一层及属性值都不是对象,使用Object.assign() === 扩展运输符[...]
if(!isObjectValue(obj)) {
return {...obj}
}
// 判断类型,如果不是Function或undefined使用JSON方式
if(!isFunctionUndefined(obj)) {
return JSON.parse(JSON.stringify(obj))
}
return cloneDeep(obj)
}