值引用和地址引用
首先我们要明白什么是值引用和地址引用
案例1
const aa={name:'张三'}
let bb=aa
bb={name:'李四'}
console.log('aa',aa);
const aa={name:'张三'}
let bb=aa
bb.name='李四'
console.log('aa',aa);
由于aa是对象,属于地址引用,当let bb=aa时,bb和aa指向了同一个地址。如果此时改变bb的值,则有两种情况
1)令bb.name='李四',此时会改变aa,而不是创建了一个新的对象,因为他们指向同一个地址
2)令bb={name:'李四'},此时不会改变aa的值,因为创建了一个新的对象,并将该对象的引用赋值给了 bb 。这时 aa 和 bb 指向的是不同的对象,因此修改 bb 不会影响 aa
案例2
在vue2的data中定义一个对象,然后用计算属性得出一个newP,当改变了newP中的name,我们会发现原始数据person中的数据也发生了改变,这就是因为共用同一个地址导致的
data(){
return {
person: {
name: "张三",
},
}
computed: {
newP() {
return this.person;
},
}
mounted() {
this.newP.name='李四';
console.log('newP',this.newP);
console.log('person',this.person);
},
注:但是你不能这样写,this.newP={age:18},因为这样相当于是要修改computed的值了,而修改computed的值是需要写set的,否则会报错
当然,该案例还可以深入探讨,比如通过两次计算属性得到的对象,会存在地址引用问题吗?答案是会的,请看第二个小例子:
data() {
return {
obj: {
name: "张三",
school: {
highschool: "北大附中",
college: "北京大学",
},
},
};
},
computed:{
newObj() {
return this.obj;
},
newSchool() {
return this.newObj.school;
},
},
created() {
this.newSchool.highschool = "清华附中";
console.log("this.obj", this.obj);
console.log("this.newObj", this.newObj);
console.log("this.newSchool", this.newSchool);
},
案例3
const obj = {
name: '张三',
school: {
highschool: '北大附中',
college: '北京大学',
},
};
const changeFn = (option) => {
option.name = '李四';
option.school.college='清华大学'
const { school } = option;
school.highschool = '清华附中';
};
changeFn(obj);
console.log(obj);
我们发现,通过函数更改了对象中的属性值后,再次打印原对象obj时,obj已经发生了改变
案例4
const obj = {
name: '张三',
school: {
highschool: '北大附中',
college: '北京大学',
},
};
const changeFn = (option) => {
let newObj = option;
newObj.name = '李四';
newObj.school.college = '清华大学';
newObj.school.highschool = '清华附中';
newObj={}
};
changeFn(obj);
console.log(obj);
- 我们发现,和案例3类似,先把obj赋予给一个newObj,当改变newObj中的属性值时,obj最后同样发生了改变
- 那为何把newObj设置为空对象时,原始的obj并没有也变成空对象呢?这是因为一旦你执行了newObj={},就意味着给newObj分配了新的地址,因此他和obj就不再指向同一个地址了,因此就不存在引用地址的关系了
利用for循环改变数组中的值
下面我们再来看数组的两个例子:
const Arr = [
{
label: 'Level one 1',
},
{
label: 'Level one 2',
},
];
for (const i of Arr) {
console.log(i);
i.label = 'label改变了';
}
console.log('最终的Arr', Arr);
const Arr2 = [1, 2, 3];
for (let i of Arr2) {
i = 0;
}
console.log('最终的Arr2', Arr2);
是不是就一目了然啦,如果数组中的value是对象,则可以改变原数组;如果是简单数据类型,就不能改变数组,这就是值引用和地址引用的作用。