一、什么是数据类型?
首先数据分为基本数据类型和引用数据类型。而今天要说明的就是对引用数据类型的数据(对象)进行赋值、浅拷贝和深拷贝后,如果修改新对象的属性值,源对象中会发生什么变化。
二、赋值、浅拷贝和深拷贝
浅拷贝: 创建一个新对象,拷贝源对象的属性值。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。注意:当object只有一层的时候,是深拷贝
深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”。
赋值:指引用地址的拷贝。要修改赋值后的数据时,如果是引用数据类型,则会影响到原数据。
先上一个简单的示例吧,这个是用到一些基础的vue2写的一个crud,实现对列表里学生的添加,修改,删除和查询功能,其中就涉及到了引用地址的知识。
当点击编辑的时候会隐藏当前div,显示编辑部分的div
而容易出现问题的地方就是这里,因为代码中编辑按钮与学生对象进行了双向绑定,所以容易出现点击取消值仍然被修改的情况,当然也有其他写法可以避免此情况,但今天遇到了就分享一下吧~
1.先上代码,看一下这里是编辑按钮部分,一个点击事件,传入一个stu对象
<!-- 查 -->
<tr v-for="stu in students">
<td>{{stu.name}}</td>
<td>{{stu.weight}}</td>
<td>
<button type="button" @click="editStu(stu)">编辑</button>
<button type="button" @click="deleteStu(stu.name)">删除</button>
</td>
<tr>
2.编辑部分div代码,绑定了data里面的studentUpdate对象中的属性值,也是一会要用到的对象,下面还有两个单击事件
<!-- 编辑页面 -->
<div v-if="showUpdateView">
姓名:
<!-- 双向绑定到data里 -->
<input type="text" v-model="studentUpdate.name" disabled="disabled">
<br>
体重:
<input type="number" v-model="studentUpdate.weight">
<br>
<button type="button" @click="update">修改</button>
<button type="button" @click="cancel">取消</button>
</div>
</div>
3.重要的来了,edit方法,这里就用到了Object的assign方法,也就是浅拷贝!
//点击编辑页面效果
editStu(stu) {
this.studentUpdate = Object.assign({}, stu);
console.log(this.studentUpdate == stu); //这里false,也就是说引用不是同一个地址
console.log(stu); //可以看到源对象的值并无变化
this.showUpdateView = true;
}
这里可以看到复制后,如果stu对象的某属性不只一层,拷贝的是对象的该属性的引用,而不是对象本身;但因为这里stu对象只有一层,所以这两个属性成了深拷贝,就是拷贝的知识属性的值!所以studentUpdate对象与stu对象进行==内存地址比较,结果为false,也就是说两个对象并没指向同一个内存地址。而且当在输入框中写了新值,打印后结果并无变化,stu的属性值不受studentUpdate对象修改的影响。
4.再来看一下update方法,第一行将students数组对象中过滤出与当前要修改的student对象名字相同的对象的引用地址直接赋值给了student,也就是说此时如果更改属性值,直接影响到源对象的属性值了!
第二行再次用到浅拷贝,将编辑后的对象覆盖到student对象,也就是数组中源对象的属性值,浅拷贝中如果目标对象已经存在相同的属性,则会进行覆盖!
此时点击修改按钮就会修改传入对象stu的属性值!点取消就会正常显示原本的值,且不点修改,原本的值就不会发生变化!
update() {
let student = this.students.filter(o => o.name === this.studentUpdate.name)[0];
Object.assign(student, this.studentUpdate);
this.showUpdateView = false;
}
继续加油 !