你将知道:
- “传递” 值是什么意思
- 什么是按值传递
- 传递物品
- JavaScript 中没有传递引用!
介绍
当需要在 JavaScript 中分配或简单地将一个值传递给其他标识符时,我们就会看到通常所说的 按值传递 。
严格来说,JavaScript 中传递值的方式只有一种,那就是复制值,这本质上就是所谓的“按值传递”。换句话说,JavaScript 实际上只支持“按值传递” 。
然而在 JavaScript 中,绝对没有办法通过引用传递数据(至少目前是这样)。
‘传递’ 是什么意思?
基本上,每当我们在 JavaScript 中将一个标识符(即变量、常量、属性等)分配给另一个标识符时,我们所做的事情就是传递标识符。传递标识符只是将其分配给另一个标识符。
例如,如果我们有一个变量 x 并将其分配给另一个变量 y ,我们会说我们将变量 x 传递给 y 。类似地,如果我们将变量 x 作为参数提供给函数 f() ,我们再次说我们正在传递变量 x 但这次是传递给函数 f() 。
什么是按值传递?
按值传递是指通过复制其值来传递标识符。
在按值传递中,传递的标识符中存储的值被复制 ,然后其副本存储在另一个标识符中。
因此,我们说 “按值传递” ,也就是说,我们传递存储的精确值。
var text = 'Hello';
var str = text;text = 'Bye';console.log(str);那么,代码将记录值 'Hello'
首先,我们定义一个变量 text ,并将其初始化为 'Hello' 。然后,我们将 text 赋值给第二个变量 str 。完成后,我们最终修改 text ,然后输出 str 值。
现在,人们可能会认为,既然 text 已赋值给 str ,那么更改 text 也会导致 str 发生更改;但这并没有发生。这仅仅是因为 JavaScript 中的原语是按值传递的。
当我们将 text 分配给 str 时,将复制存储在 text 中的实际值 (即 'Hello' ,并将副本分配给 str 。
换句话说,变量 text 和 str 都有各自独立的 'Hello' 值;改变其中一个不会明显改变另一个。
上面的代码从技术上讲等同于下面的代码:
var str = 'Hello'; // own value
var text = 'Hello'; // own valuetext = 'Bye';console.log(str);JavaScript 数据类型不只有原始类型,对吧?我们还有对象。现在,对象传递也是按值传递的。
ha?
在 JavaScript 中,对象通过其引用 存储在标识符中, 而不是通过其实际值。
引用可以被认为是指向存储对象位置的内存地址。
由于 JavaScript 中的对象通过其引用存储在标识符内,因此当传递该对象时,实际传递的是该引用。
对象是真实的数据;引用是对象在程序中的表示方式。
再次强调,需要特别注意的是,对象仍然像 JavaScript 中的原语一样传递,即按值传递;对象唯一的不同之处在于它们的存储方式,即通过引用。
var obj = { x: 10 };
var obj2 = obj;obj.x = 20;console.log(obj2.x); // 20 我们首先定义一个变量 obj ,其值为 { x: 10 } 然后定义另一个变量 obj2 ,并将其初始化为 obj。
接下来,我们改变 obj 的属性 x ,然后记录 obj2 的相同属性。
obj.x 在 obj2 中可见,仅仅是因为 obj 和 obj2 都引用内存中 obj 同一个对象 。obj 和 obj2 不保存单独的对象 - 它们保存完全相同的对象。

JavaScript 中对象是如何存储的
这是我们的 obj 变量。它包含一个指向内存中对象 { x: 10 } 的值(箭头所示)。这个值就是我们所说的引用。
当我们将 obj 赋值给另一个变量 obj2 时,会发生以下情况:

在 JavaScript 中将对象分配给另一个标识符
obj 中存储的值(引用)仅仅被复制到 obj2 中。因此, obj2 指向(箭头所示) obj 指向的同一个对象 { x: 10 } 。
如果我们现在继续更改 obj 的属性,就像我们在上面的代码中通过更新属性 x 所做的那样,那么该更改在 obj2 中也会可见。
重申一下:
当我们将 obj 分配给 obj2 时, obj 中存储的实际值 (即引用 )被复制,并将该副本分配给 obj2 。 实际也还是值传递,只是这个值是引用。
从今以后,如果我们改变存储在 obj (或 obj2 )中的对象,这些变化显然也会在 obj2 (或 obj )中可见,因为它们都包含完全相同的对象。
(牢记上面的图)
JavaScript 中没有传递引用!
你不能真正在 JavaScript 中通过其引用(在内存中)传递标识符,并期望其他代码能够控制该标识符中存储的内容。
事实上,很容易确认传统意义上的 JavaScript 不支持传递引用。
以上面部分的代码为例,如果我们将任何值重新分配给 obj 或 obj2 本身,另一个变量不会发生神奇的变化。
var obj = { x: 10 };
var obj2 = obj; // This is just pass-by-value.obj = 20;console.log(obj2);{ x: 10 }这里的一切与之前相同,只是现在变量 obj 自身发生了改变(而不是像之前那样改变其属性 x )。然后,直接输出 obj ,而不是输出 obj.x 。
因为 JavaScript 中没有真正意义上的按引用传递,所以我们在为 obj 分配值时, obj2 不会改变 - 它会继续保留 { x: 10 } 。

这纯粹是因为没有任何东西将两个变量 obj 和 obj2 联系在一起。

简单来说就是,本来他俩的值都是引用,比如 16 位一个引用地址,指向了内存中的{x: 10},所以,当 xxx.x 的时候,才会影响这两个对象,但实际他俩是两个变量,当 obj = 20 的时候, 那就是一个原语,最基础的值 20。那么得到的结果当然就是 obj = 20 , obj2 = {x:10}