值和引用
Posted passerbyone
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了值和引用相关的知识,希望对你有一定的参考价值。
引用《你不知道的JavaScript》中卷 2.5值和引用
在许多编程语言中,赋值和参数传递可以通过值复制(value-copy)或者引用复制 (reference-copy)来完成,这取决于我们使用什么语法。
例如,在 C++ 中如果要向函数传递一个数字并在函数中更改它的值,就可以这样来声明参 数int& myNum,即如果传递的变量是x,myNum就是指向x的引用。引用就像一种特殊的指 针,是来指向变量的指针(别名)。如果参数不声明为引用的话,参数值总是通过值复制 的方式传递,即便对复杂的对象值也是如此。
javascript 中没有指针,引用的工作机制也不尽相同。在 JavaScript 中变量不可能成为指向 另一个变量的引用。
JavaScript 引用指向的是值。如果一个值有 10 个引用,这些引用指向的都是同一个值,它 们相互之间没有引用 / 指向关系。
JavaScript 对值和引用的赋值 / 传递在语法上没有区别,完全根据值的类型来决定。
下面来看一个例子:
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]
简单值(即标量基本类型值,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],不是[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 共同指向的值。
以上是关于值和引用的主要内容,如果未能解决你的问题,请参考以下文章