JS 中的赋值运算符是(重新)绑定还是突变?

Posted

技术标签:

【中文标题】JS 中的赋值运算符是(重新)绑定还是突变?【英文标题】:Is the assignment operator in JS a (re)binding or a mutation? 【发布时间】:2016-11-21 12:30:24 【问题描述】:

我试图了解 javascript 中的赋值运算符是否应该用作(重新)绑定,而不是突变。换句话说,给定以下内容:

let x = 10;
x = 20;

我想了解第二行是否导致编码值 10 的位被修改以对值 20 进行编码,或者 - 或者 - 如果 x 标识符与其他标识符反弹(可能是新的)内存块,已初始化为包含值20

后一种选择是我发现的常见解释(例如,在 ECMA-262-5 in detail 中)。这种解释的好处是它允许将原始类型表示为不可变的值,并将突变限制为单独对object 类型的操作。

但是,每次执行赋值时绑定到不同内存块的想法看起来很奇怪,尤其是考虑到在 C 和 C++ 等语言中如何执行相同的操作时。实际上,在 C(和 C++)中,赋值会导致与标识符相关的位发生突变,同时保留变量标识。那就是:

int x = 10;
cout << &x << endl;
x = 20;
cout << &x << endl;

将打印相同的地址。相反,重新绑定会导致x 在内存中的位置发生变化。

很遗憾,我在标准中找不到解释。有没有我可以依赖的权威来源?如果——相反——这取决于供应商,最常见的方法是什么?

谢谢。

编辑:我改写了那些提到“新记忆块”的句子,因为它们使讨论产生了偏见。我最感兴趣的是了解分配操作是否是 JS 是一个身份保持操作。

【问题讨论】:

即使是重新绑定,只要保留正确的语义,也不需要分配新的内存块。 你如何分辨? @melpomene:我的问题更多是关于如何以最忠实的方式描述JS中赋值运算符的语义。从外部看,这两种方法没有区别,因为无法检查每个变量的内存位置。 @DarkFalcon:我从提到的参考资料中参与了绑定到新块的部分,这是我能找到的最权威的来源。但是,我最感兴趣的是了解 JS 中的赋值操作是否是一个身份保持操作。 这是一个突变,因为闭包会看到更新:let x = "foo"; let f = function () return x; ; x = "bar"; console.log(f()); 输出 "bar" 【参考方案1】:

赋值是变量的突变,以保持与以前不同的值。

该值是否存储在一块内存中并且仅由变量的内容引用,或者编码在变量本身的内容中,对于不可变的原始值(例如 1020.

然而,对象值只是明确的引用,如您链接的文章中所示。

每次执行分配时分配一个新内存块的想法看起来很奇怪

这确实不会发生。即使赋值只是改变一个引用,被引用的内存(包含值)在赋值之前就已经存在了。

【讨论】:

以上是关于JS 中的赋值运算符是(重新)绑定还是突变?的主要内容,如果未能解决你的问题,请参考以下文章

js学习笔记

Js中的运算符

赋值运算符中的引用返回[重复]

函数式编程 JS 中的数组赋值

从复制构造函数调用默认赋值运算符是不好的形式吗?

js连续赋值