在Javascript中分配对象:浅拷贝还是深拷贝?

4
我想知道在复制对象时,JavaScript会进行浅复制还是深复制。
const a = ['value1', 'value2'];
const b = ['value3', 'value4'];
const new_ab = [a, b];

new_ab会有新分配的值或者引用吗?如果是深拷贝,如何使其成为浅拷贝?谢谢。

(Note: I kept the HTML tags and made the text more clear and concise.)

1
ab是对数组的引用,因此new_ab将是一个包含这些引用的数组的引用。在您发布的代码中根本没有复制任何对象。 - Pointy
1
你可以通过对new_ab [0]进行变异并观察对a的影响来轻松检查这一点。 - Blender
那么,使用上述代码是高效的,因为它们只是引用吗? - Mateus Felipe
1个回答

1
正如评论中所提到的,JavaScript 完全基于引用操作。唯一的例外是原始值存储在堆栈上,因此程序不需要引用即可访问它们。在您的示例中,所有变量声明都创建新值 - 每个值都是 Array 的一个实例。但是,从声明数组返回的是引用,而不是数组本身。例如,[1, 2] 是一个值(整数)数组,但 [a, b] 是一个引用数组。

所以...没有任何复制。我们可以通过将对象作为数组元素并检查以前分配的属性是否仍然可以通过新的“父”数组访问来证明这一点。

(回答评论中的问题,是的,您的示例比如果您(或 JavaScript)复制值更有效率。)

'use strict';

const arrayOne = [];

arrayOne.someProperty = "This string is a property of `arrayOne`, " +
                        "accessed via the reference to it in `arrayTwo`."

const arrayTwo = [arrayOne];

span.innerHTML = arrayTwo[0].someProperty;
<span id="span"></span>


1
“唯一的例外是原始值保留在堆栈上,因此程序不需要引用。”您是如何知道的?您能参考规范吗?另外,这对闭包有什么影响? - Felix Kling
@FelixKling 并非所有的原始值都存储在栈上。这些值的处理方式是规范要求的实现细节。当闭包需要一个原始值时,编译器会将该值放在堆上。参考资料可见这里这里,虽然是个人经验,但是这是我所拥有的除了阅读v8源代码外的参考资料。 :) - sdgluck
我承认在引用语句上有些宽泛,但是将原始值存储在堆栈中的原则适用于许多面向对象编程语言。当发生强制转换和其他类似操作,或者像你所说的在闭包内引用一个值时,这个原则可能会被颠覆。 - sdgluck
那基本上就是我的观点:这是一项实现细节,而且它并不普遍适用,因此该陈述是不正确的。在我看来,这也与问题无关。 - Felix Kling
@FelixKling 好的,没问题。我只是觉得这是一个有趣的小细节! - sdgluck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接