Skip to content

传值与传址?

Published:

传值(Pass by Value)

在 JavaScript 中,当变量的值是原生类型时,就是传值

如果传递的变量是原生类型时,传递的就会是值的副本,而不是传递变量的内存位置。我们可以使用 = 来赋予变量一个值举以下的例子,分别赋予不同数字给 a、b:

const a = 1;
const b = a + 1;

可以注意到第 2 行,将 b 指定为 a 的值 +1,这时候 c 的值就会是 1 + 1 = 2,非常直观也很好理解,这就是所谓的「传值(Pass by value)」

原生类型具体来说有:String、Number、Boolean、Undefined、Null,这些类型的数据是以「值」的方式来传递。

传址 (Pass by reference)

在 JavaScript 中,当变量不是原生类型时,就是传址。

当变量是对象或数组的情况下,JavaScript 会需要额外的记录代表其内存位置,因此变量内存储的并不是实际的内容,而是一个内容所在的内存位置。举以下图表为例,图表中的 b 变量实际上持存的是内存位址:

const a = 1;
const b = [1, 2];
变量内存位址​
a1A
b[1, 2]BA

了解了传址的概念后,我们来延伸前面的例子,如果这时候有个变量 c = b 那么画成图表就会是这样:

const a = 1;
const b = [1, 2];
const c = b;
变量内存位址
a1A
b[1,2]BA
c[1,2]CA

如此一来 b 与 c 所指向的内存位置都是 A,因此当我们对 c 做修改时,b 也会跟着改变:

let a = 1;
let b = [1, 2];
let c = b;
b.push(3);
// 结果:b 与 c 都变成 [ 1, 2, 3 ] 了!

这也是为什么 b 与 c 的值都会变成 [1, 2, 3],因为 b 与 c 都指向了同一个内存位置。

相等但不相等

了解前面传值与传址的差异后,会发现内存位置与值是全然不同的东西,一个是指针,一个是内容,实际就像以下图表示例。

const a = [1, 2];
const b = [1, 2];

console.log(a === b); // false - 内存地址不一致
变量内存位址
a[1,2]A
b[1,2]A
let a = [1, 2];
let b = a;
console.log(a === b); // true - 内存地址一致
变量内存位址
a[1,2]A
bA

总结

了解 JavaScript 是如何储存变量有助于更好的操控数据,避免出现改 A 却动到 B 的状况。

参考资料

Reference Vs Value - Most People Don’t Understand This