<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script>
//一、浅拷贝
//1.区分值类型-和-引用类型
//1-1.值类型-值的复制(基本类型):字符串(string)、数值(number)、布尔值(boolean)、undefined、null ;
//1-2.引用类型-内存地址复制:对象(Object)、数组(Array)、函数(Function)
// 1-1.案例
let a = 100;
let b = a;
a = 50;
console.log('a',a)//50
console.log('b',b)//100
//浅拷贝基本类型之前互不影响-值的复制
//a 100
//b 100
//a 50
// 1-2.案例-数组
let arr = ['小米','华为']
let brr = arr
arr.push('ios')
console.log('arr',arr)//['小米','华为','ios']
console.log('brr',brr)//['小米','华为','ios']
//堆内存-arr内存地址-brr指向arr的内存地址-所以内容是相互影响的-内存地址复制
//引用类型其中一个对象改变了地址,就会影响另一个对象
//arr ['小米','华为']
//brr ['小米','华为']
//arr ['小米','华为','ios']-引用类型其中一个对象改变了地址,就会影响另一个对象
//brr ['小米','华为','ios']-相互影响
// 1-2.案例-对象
let obj = {
name:'小李',
age:18
}
let obj2 = obj
obj.name = '小刘'
console.log('obj',obj.name)//{name:'小刘',age:18}
console.log('obj2',obj2.name)//{name:'小刘',age:18}
//2.对象拷贝的几种方法(把数组拷贝一份新的,和原数组脱离关系)
//方法1:创建新对象-循环遍历
let duix = {
name:'小明',
age:18
}
let duix2 = {}
for(let key in duix){
duix2[key] = duix[key]
}
//使用方法后,不会修改原对象--返回一个新的对象,不影响原对象
duix.name = "小红"
console.log('duix',duix.name)//{name:'小红',age:18}
console.log('duix2',duix2.name)//{name:'小明',age:18}
//方法1:延申-创建新数组-循环遍历
let newarr = ['小米','华为']
let newbrr = [];//新数组
for(let i = 0;i<newarr.length;i++){
newbrr.push(newarr[i])
}
newarr.push("ios")
console.log('newarr',newarr)//['小米','华为',"ios"]
console.log('newbrr',newbrr)//['小米','华为']
//方法2:Object.assign 只有一层关系
const videoc = {like:100,action:2};
const videoForwardc = Object.assign({}, videoc);;
videoForwardc.action = 10000;
console.log('videoc:'+videoc)//{like:100,action:2}
console.log('videoForwardc:'+videoForwardc)//新创建了一个空{} = {like:100,action:1000}
//方法2:Object.assign 有二层关系时,第一层不相互影响,第二层会相互影响
const video = {like:100,action:{say:2}};
const videoForward = Object.assign({}, video);;
video.action.say = 10000;//第二层
videoForward.like = 50;//第一层
console.log('video:'+video)//{like:100,action:{say:10000}}
console.log('videoForwardactionsay:'+videoForward)//新创建了一个空{} ={like:50,action:{say:10000}}
//方法3:es6展开运算符
const videoa = {like:100};
const videoForwarda = {...videoa};
videoForwarda.like = 10000;
console.log('videoa:'+videoa.like)//{like:100}
console.log('videoForwarda:'+videoForwarda.like)//{like:10000};
// 总结:
//1.值类型-赋值时-是值的复制(不会相互影响)
//2.引用类型-赋值时-是内存的指向-指向同一个内存地址(相互影响)
//3.拷贝有2种情况,如果处理内容第一层关系时,是创建一个新的内存地址,他们是不会相互影响的,如果处理内容第二层关系时,他是会指向同一个内存地址,是会相互影响的
//1.什么是浅拷贝?
//把数组/对象第一层的值,复制到新的数组/对象中
//2.浅拷贝的使用场景?
//修改数组/对象,影响另一个数组/对象,"砍断"他们的联系
//3.如何实现浅拷贝?
//for/for...in/es6的扩展运算符/es5 Object.assign()/concat(),slice()也属于浅拷贝
//4.浅拷贝的注意点!
//只拷贝第一层的值,第二层互相影响
// 二、深拷贝
// 1.如何解决第二层的值互相影响的关系呢?
const newvideo = {like:100,action:{say:2},arr:["小米","红米"]};
// const newvideoForward = Object.assign({}, newvideo);;
// newvideo.action.say = 10000;//第二层
// newvideoForward.like = 50;//第一层
//console.log('video:'+newvideo)//{like:100,action:{say:10000}}
//console.log('videoForwardactionsay:'+newvideoForward)//新创建了一个空{} ={like:50,action:{say:10000}}
//递归函数
//注意:先写Array类型的判断(因为Array的父类是Object,写在上面无论数组对象都会进去)
let NewObj = {}
function deepClone(newo,old){
for(let key in old){//key:"licke" "action"
let value = old[key]//value: 100 {say:2}
if(value instanceof Array){
newo[key] = [];//被拷贝的是数组,创建一个新的数组
deepClone(newo[key],value)//递归
}else if(value instanceof Object){
newo[key] = {};//新对象
deepClone(newo[key],value)//递归
}else{
newo[key] = value;//基础类型,单纯复制
}
}
}
deepClone(NewObj,newvideo)
NewObj.arr.push("红马甲")
NewObj.action.name = '张名'
NewObj.like = '66'
console.log("newvideo",newvideo)//{like:100,action:{say:2},arr:["小米","红米"]};
console.log("NewObj",NewObj)//{like:66,action:{say:2,name:'张名'},arr:["小米","红米","红马甲"]};
debugger
// 总结:
//1.什么是深拷贝?
// 把数组/对象所有层的值,复制到新的数组/对象中
//2.如何实现深拷贝?
//创建新数组/对象
//判断基础类型,直接赋值
//判断对象类型,递归调用函数,继续创建判断
</script>