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]