即使作为一个有点经验丰富的JS开发人员,我发现自己也常常对浅物和副物的副本感到惊讶。
对于何时通过引用复制JavaScript值而不是主要对象类型的值,是否有任何经验法则?例如,我知道字符串值总是按值而不是引用复制。
答案 0 :(得分:4)
在JavaScript中,所有对象都存储并通过引用传递。
var a = { v: 'a' }, b = { v: 'b' };
a=b;
b.v='c';
a
和b
将引用同一个对象; a.v == 'c'
和b.v == 'c'
。
原始数据类型(string
,number
,boolean
,null
和undefined
)是不可变的;它们是按价值传递的。
var a = 'a', b = 'b';
a=b;
b='c';
由于我们正在处理基元a == 'b'
和b == 'c'
。
Pedants会告诉你JavaScript在传统意义上不是传递引用,或者它是一种“纯粹的传值”语言,但我认为这样做会使实际目的复杂化。不,你不能直接修改传递给函数的参数,就好像它是一个变量(如果语言是真正的传递引用就是真的),但是你也没有收到副本< / em>作为参数传递的对象(如果它是真值pass-by-value那样)。对于大多数用途(从语言用户的角度来看),传递给函数的对象是引用,因为您可以修改该对象并且它会影响调用者的对象。另请参阅fantastic answers to this question。
答案 1 :(得分:2)
好的,让我解释一下你的代码:
var x, y;
x = { 'blah': 'foo' };
y = x;
x = { 'bar': 'bas' };
因此,您声明了两个变量,然后将对象值分配给第一个变量:
x = { 'blah': 'foo' };
那么,这里会发生什么:
{ ... }
- ,这将导致创建和初始化新的本机对象。x
。接下来,这一行
y = x;
仅将存储在x
中的参考复制到变量y
。现在两个变量都存储对象的相同引用。
最后,这一行
x = { 'bar': 'bas' };
为变量x
指定一个新值。评估对象文字导致另一个对象的创建/初始化,并且对该对象的引用存储在x
中。
但是,变量y
仍然保留对第一个对象的引用。