几个案例让你搞懂地址引用

114 阅读4分钟

在JavaScript中,变量存储的不仅仅是值本身,很多时候它们还保存着对某个内存地址的引用。这种特性使得JavaScript在处理数组、对象等复杂数据结构时展现出独特的行为模式。本文将通过一系列具体的示例来深入探讨JavaScript中的地址引用机制,特别是如何理解和利用这一特性来优化代码逻辑与性能。通过这些案例,希望能帮助读者更好地理解JavaScript中的引用概念,并能够灵活运用到实际开发中。

案例1

const a = {
  student: [{ name: '张三' }]
};
let b = a.student;// b 指向 a.student 所引用的数组  
b = [{ name: '李四' }];// b 现在指向一个新的数组,与 a.student 不再共享引用  

console.log(a, b);// a.student 仍然是 [{ name: '许怀玉' }],而 b 是 [{ name: '李四' }]


案例2

const a = {
  student: [{ name: '张三' }]
};
let b = a.student;// b 指向 a.student 所引用的数组  
b.length=0;// 清除 b(即 a.student)中的所有元素  
b.push({ name: '李四' });// 在 b(即 a.student)中添加一个新元素

console.log(a, b);// a.student 和 b 现在都是 [{ name: '李四' }]


请问上面哪个案例中,a会随着b改变呢?

详解

答案是案例2

在JavaScript中,对象(包括数组,因为数组在JavaScript中也是对象)是通过引用传递的。这意味着当你将一个对象赋值给另一个变量时,这两个变量实际上指向内存中的同一个对象。但是,当你将一个数组赋值给另一个变量时,如果你赋的是一个新数组(即一个新的引用),那么这两个变量就不会再指向同一个对象。

在案例1中:a 不会随着 b 的改变而改变,因为 b 被重新赋值为一个新的数组对象。

在案例2中:a 会随着 b 的改变而改变,因为 b 和 a.student 指向的是同一个数组对象。当你通过 b 修改数组(如清空数组或添加新元素)时,这些修改会反映到 a.student 上,因为它们引用的是同一个数组。

拓展1

可以三个对象一起引用一样的地址吗?比如我让b等于一个地址,改了另一个,a和b都改变

当然可以。在JavaScript中,当多个变量引用同一个对象(包括数组)时,这些变量都指向同一个内存地址。因此,通过任何一个变量对这个对象进行的修改都会反映到所有引用该对象的变量上。

案例A

/ 假设我们有一个对象(或数组)  
const obj = { name: '许怀玉', age: 20 };  
  
// 现在我们让a、b、c都引用这个对象  
let a = obj;  
let b = obj;  
let c = obj;  
  
// 通过b修改对象的属性  
b.name = '李四';  
  
// 由于a、b、c都引用同一个对象,所以修改会反映到所有变量上  
console.log(a.name); // 输出: 李四  
console.log(b.name); // 输出: 李四  
console.log(c.name); // 输出: 李四  
  
// 同理,如果是一个数组  
const arr = [1, 2, 3];  
let d = arr;  
let e = arr;  
let f = arr;  
  
// 通过d修改数组  
d.push(4);  
  
// 修改会反映到所有引用该数组的变量上  
console.log(d); // 输出: [1, 2, 3, 4]  
console.log(e); // 输出: [1, 2, 3, 4]  
console.log(f); // 输出: [1, 2, 3, 4]

拓展2

如果

const arr = [1, 2, 3];  // arr 引用了一个包含三个元素的数组  
let d = arr;            // d 也引用了相同的数组  
let e = arr;            // e 同样引用了相同的数组  
let f = arr;            // f 也引用了相同的数组  
f = [100, 200];         // 这里,f 被赋值为一个新的数组,它不再引用之前的数组
 

这段关系中,f和d e都指向arr这个地址,但是最后f改变了,会影响到d e吗?

不会,这段代码中 f 的改变不会影响到 d 和 e

在JavaScript中,当您使用 let 或 const 声明一个变量并给它赋一个数组(或对象)时,该变量实际上存储的是对数组(或对象)的引用(即内存地址)。但是,当您给这个变量赋一个新的数组(或对象)时,它不会更新原始数组(或对象),而是会让这个变量引用一个新的数组(或对象)。