【问题标题】:Reassignment, mutation, reference types, and value types重新赋值、变异、引用类型和值类型
【发布时间】:2016-03-18 23:11:42
【问题描述】:

您将如何恰当地解释这两个示例为何不同?

// Reassignment
let a = 1;
let b = a;
a = 2;
console.log(b); // → 1

// Mutation
let myArray = [1, 2, 3];
let ourArray = myArray;
ourArray[2] = 10;
console.log(myArray); // → [1, 2, 10]

关于为什么变量标签在两者之间的行为不同,许多资源声称这是因为引用类型和值类型之间的差异。但是,这不只适用于 values 本身之间的差异吗?

当明确谈论变量标签时(即为什么第一个示例中的标签不跟踪值的更改,而在第二个示例中却跟踪),真正的区别与 无关突变与重新分配

毕竟,我们可以很容易地重新分配 myArray 或 ourArray 并且它们都不会有任何类型的持续链接。而且,如果 JavaScript 中的原始值在理论上是可变的,那么第一个示例的行为就可以与第二个示例一样。

后续问题

我还阅读了关于原始值是否仅在内存中存在一次的相互矛盾的信息。例如,如果第一个在内存中只存在一次,那么将变量标签可视化为名称标签是合适的,每个引用第一个的名称标签都“卡”在同一个数字上,对吗?

同样,如果第一号能够发生变异,那么每个名称标签都会跟踪该第一号的相同变化。但由于一个是不可变的,名称标签可以继续引用相同的数字 1,也可以将它们取下并粘贴到不同的值(重新分配)。

我在正确的轨道上吗?

【问题讨论】:

  • 我认为您错过了使用低级语言(带指针)的体验。 5天的pascal苦苦挣扎,可以省去你50天的js苦苦挣扎,一切都会清晰得多。
  • 是的,这是一个关于可变值与不可变值的突变与重新分配的问题。是否一次只有一个 9 的实例存在于内存中?可能,假设它是实际值,而不是您分配其他属性的 Number object,但这完全取决于编译器如何处理它。

标签: javascript variables reference immutability key-value


【解决方案1】:

您在问题中将实现细节(“在内存中存在一次”)与评估策略(“引用类型和值类型”)和特定表达式(“突变与重新分配”)混合在一起。不同浏览器的实现细节不同,未来可能会发生变化。

Javascript 中有两种评估策略:

  • 按值复制(调用函数时按值传递)
  • 按引用复制(调用函数时按引用传递)

值类型

值类型总是按值复制。假定字符串在 Javascript 中是可变的:

let s = "abc";
let t = s;

s[0] = "x";
s; // "xbc";
t; // "abc";

基于值类型的变量(或标识符或名称绑定)直接包含它们的值。如果这样一个可变字符串发生了变异,那么只有对应标识符的值会受到影响。

与字符串不同,数字是原子的。对于原子原语,突变和重新分配没有实际区别:

let n = 0;
n = 1, n++, n = n + 1; // all reassignments

参考类型

持有引用类型的变量只包含对该类型的引用,它在 Javascript 中是一个复杂的值(对象)。如果两个变量引用同一个对象,它们每个都保存这个引用的副本,而不是直接别名。因此,如果重新分配两个变量之一,这不会影响另一个。

引用类型具有标识,即它们的标识不再与值绑定:

let xs = [1];
xs === [1]; // false

【讨论】:

  • 在您的示例中,s"abc" 而不是 "xbc"
【解决方案2】:

当明确谈论变量标签时,真正的区别不是与变异与重新分配有关吗?

当然。我假设您的意思是一个 mutates 对象和 assigns 变量。但你不能总是这样区分它们。我也可以说我分配给对象属性(在您的第二个示例中)或变异“变量标记”内存单元(在您的第一个示例中)。真的有区别吗?

但事实上,变量(标签、内存单元、寄存器)的工作方式总是相同的,无论它是保存原始值还是引用值。

我一直在阅读关于原始值是否在内存中只存在一次的相互矛盾的信息。

嗯,重点是没关系,因为原始值(根据定义)是不可变的。一个 JS 实现可以复制它们,或者共享引用,脚本无法区分行为。

在现实世界中,数字和布尔值通常是复制的,而字符串通常是 interned(共享)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 2018-08-27
    • 2012-07-20
    相关资源
    最近更新 更多