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]
JavaScript
引用指向的是值。如果一个值有
10
个引用,这些引用指向的都是同一个值,
它
们相互之间没有引用
/
指向关系
。
简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值 / 传递,包括
null
、
undefined
、字符串、数字、布尔和
ES6
中的
symbol
。
复合值(
compound value
)——对象(包括数组和封装对象,参见第
3
章)和函数,则
总
是
通过引用复制的方式来赋值
/
传递。
上例中
2
是一个标量基本类型值,所以变量
a
持有该值的一个复本,
b
持有它的另一个复
本。
b
更改时,
a
的值保持不变。
c
和
d
则分别指向同一个复合值
[1,2,3]
的两个不同引用。请注意,
c
和
d
仅仅是指向值
[1,2,3]
,并非持有。所以它们更改的是同一个值(如调用
.push(4)
),随后它们都指向更
改后的新值
[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]
并不影响
a
指向值
[1,2,3]
,除非
b
不是指向数组的引用,而是指向
a
的指针,
但在
JavaScript
中不存在这种情况!
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]
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]
我们向函数传递 a 的时候,实际是将引用 a 的一个复本赋值给 x,而 a 仍然指向 [1,2,3]。
在函数中我们可以通过引用
x
来更改数组的值(
push(4)
之后变为
[1,2,3,4]
)。但
x =
[4,5,6]
并不影响
a
的指向,所以
a
仍然指向
[1,2,3,4]
。
我们不能通过引用
x
来更改引用
a
的指向,只能更改
a
和
x
共同指向的值。
如果要将
a
的值变为
[4,5,6,7]
,必须更改
x
指向的数组,而不是为
x
赋值一个新的数组。
function foo(x) {
x = x + 1;
x; // 3
}
var a = 2;
var b = new Number( a ); // Object(a)也一样 // Number {2}
foo( b );
console.log( b ); // 是2,不是3