在我们学的越来越多,学的越来越杂的时候,如果一些基础却还没有到位,这样为我们后面的学习和写代码是留下了非常多的隐患的,对于后面的学习,导致学习的效率变慢,需要重新学习前面已经学习过的知识,对于写项目,写代码,也是有着极大的影响的,在不知不觉中就会在项目中留下大大小小的隐患,如果只是一个,两个bug还比较容易解决,如果很多的bug耦合在一起,到时候再来排除bug的时候,真的是痛不欲生。
一、++表达式
let a = 1
let b = a + ++a + a++
当我们在代码中遇到这么一段代码的时候,你能不运行代码,根据自己的开发知识得到a和b的值吗?
遇到这个问题,我们都知道++会将a自增一次,那么自增的时机是什么呢?
当++在变量之前时 ++a
1.先自增 2.返回结果
当++在变量之后时 a++
1.先返回结果 2.再自增
这个时候我们再来看代码
//当代码运行到++a时(a=2) 先自增,再返回
let b = 1 + (1+1) + a++
//当代码运行到a++时(a=3) 先返回,再自增
let b = 1 + (1+1) + 2
//b=5,a=3
二、对于引用类型数据的赋值
这里的引用类型主要针对对象和数组
//对象类型的直接赋值
let obj = {
name:"lihu",
age:"18"
};
let newObj = obj;
obj.age = 19;
//数组类型的直接赋值
let arr = [1,2,3,4];
let newArr = arr;
arr[1] = 100;
当我们想在写代码的时候,大家思考一下对应的newObj和newArr的值应该是多少
解析:当数据为引用类型的数据时,例如对象,对象中存放的是指向每一个属性的指针,而属性值另外存放在一个堆中,当我们直接赋值,两个对象中存放的指针都同时指向同一个属性值,当我们改变其中一个对象的属性时,另一个对象也会受到影响。
想要摆脱这种影响,需要对对象进行拷贝(浅拷贝or深拷贝)
浅拷贝:只拷贝一层
那么我们如何在代码中书写呢?这里以js为例子
let obj = { a:1 }
//将对象解构,将解构的结果用对象包裹起来,
//这样新得到的对象存储的地址就将是一个新的值,原本的对象的属性值改变也不会影响到新的对象
let newObj = {...obj}
let arr = [1]
//数组同理
let newArr = [...arr]
深拷贝:将对象所有属性完完全全拷贝
上面的浅拷贝只适用于一层的数据结构,当遇到多层结构时就不太适用了,例如:
//多层结构的对象
let obj = {
studentName:"李四",
studentCard:{
cardId:"10001",
...
}
...
}
//多层结构的数组
let arr = [[1,2],[1,2,3],[3]...]
当对象和数组呈现出多层结构时,只是简单的浅拷贝就不行了,原因:
例如上面的对象例子,当解构到studentCard属性的时候,由于它是一个对象,所以存放的还是同一个地址,数组同理,所以将这些数据进行简单的浅拷贝赋值给另外的对象或者数组时,修改原本的对象中的引用类型的数据时还是会影响新对象或新数组。
使用深拷贝,在js中提供一些方法,能帮助我们实现深拷贝
方法一:JSON字符串
//将对象转化为json字符串
let jsonString = JSON.stringify(obj)
//再将json字符串转化为对象
let newObj = JSON.parse(jsonString)
这种方法虽然简单,但是也有一些比较致命的缺点,就是不能处理一部分特殊的数据 例如:
let a = {
name: 'Jack',
age: 18,
hobbit: ['sing', {type: 'sports', value: 'run'}],
score: {
math: 'A',
},
run: function() {},
walk: undefined,
fly: NaN,
cy: null,
date: new Date()
}
let b = JSON.parse(JSON.stringify(a))
console.log(b)
// {
// age: 18,
// cy: null,
// date: "2022-05-15T08:04:06.808Z"
// fly: null,
// hobbit: (3) ["dance", "sing", {…}],
// name: "Jack",
// score: {math: "A"},
// }
方法二:递归函数实现深拷贝
在实现这个方法的时候,无非就是需要注意当前传入参数的类型
//深拷贝
const cloneDeep = (obj) =>{
// 传入的对象的类型不是引用数据类型,
// 返回
if(typeof obj !=='object' || obj === null){
return obj
}
//但是这里的obj可能有两种情况
let resultObj
//判断是数组还是对象
if(obj instanceof Array){
resultObj = []
}
else{
resultObj = {}
}
for (let key in obj) {
resultObj[key] = cloneDeep(obj[key])
}
return resultObj
}
//测试数据
const obj = {
name:"王五",
age:18,
class:undefined,
children:[
{
id:1,
children:[
{
id:2
}
]
}
]
const obj2 = cloneDeep(obj)
obj2.name = '李四'
obj2.children[0].id = 1000
console.log("obj",obj);
console.log("obj2",obj2);
然后我们再来看一看最终的结果
修改克隆出来的数据并没有影响到原本的数据,也代表我们的这个方法是实现成功了的
方法三:使用别人的库
使用步骤如下 ` 1.下载依赖
npm i --save lodash
2.引入具体使用的页面
import _ from 'lodash'
3.使用方法进行深拷贝
import _ from 'lodash';
const data = {
id:"1",
parentId:"0"
name:"码表一",
children:[
{
id:"2",
parentId:"1",
name:"码值一"
},
...
]
}
const copyData = _.cloneDeep(data)
上面这3个步骤就是使用lodash深拷贝的具体流程了