你不知道的 JavaScript 系列中, 15 - 值和引用

JavaScript 引用指向的是值,如果一个值有 10 个引用,这些引用指向的都是同一个值,它们相互之间没有引用/指向关系。JavaScrtip 对值和引用对赋值/传递在语法上没有区别,完全根据值的类型决定。

var a = 2;
var b = a; // b 是 a 的一个副本
b++;
a; // 2
b; // 3

var c = [1,2,3];
var d = c; // d 是 [1,2,3] 的一个引用
d.push(4);
c; // [1,2,3,4]
d; // [1,2,3,4]

简单值,是通过复制的方式来赋值/传递,复合值则总是通过引用复制的方式来赋值/传递。

由于引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向

var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]

//然后
b = [4,5,6];
a; // [1,2,3];
b; // [4,5,6]

b = [4,5,6] 为 b 赋值了一个新的数组,b = [4,5,6] 并不影响 a 指向值[1,2,3]。如果要改变 a 的值,必须更改 b 指向的数组。d.push() 并没有创建一个新的数组,而是更改了当前的数组,于是 c 变成了 [1,2,3,4]

函数参数就经常让人产生这样的疑惑:

function foo(x) {
  x.push(4);
  x; // [1,2,3,4]

  //然后
  x = [4,5,6];
  x.push(7);
  x; // [4,5,6,7]
}
var a = [1,2,3];
foo(a);
a; // 是[1,2,3,4],不是[4,5,6,7]

同理,这里 x = [4,5,6,7] 创建了一个新的数组,并不影响 a 的指向,不能通过引用 x 来更改引用 a 的指向,只能更改 a 和 x 共同指向的值,如果要将 a 的值变为 [4,5,6,7] 必须更改 x 指向的数组,而不是为 x 赋值一个新的数组

function foo(x) {
  x.push(4);
  x; // [1,2,3,4]

  //然后
  x.length = 0; // 清空数组
  x.push(4,5,6,7)
  x; // [4,5,6,7]
}
var a = [1,2,3];
foo(a);
a; // 是[4,5,6,7],不是[1,2,3,4]