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】:
赋值是变量的突变,以保持与以前不同的值。
该值是否存储在一块内存中并且仅由变量的内容引用,或者编码在变量本身的内容中,对于不可变的原始值(例如 10
和20
.
然而,对象值只是明确的引用,如您链接的文章中所示。
每次执行分配时分配一个新内存块的想法看起来很奇怪
这确实不会发生。即使赋值只是改变一个引用,被引用的内存(包含值)在赋值之前就已经存在了。
【讨论】:
以上是关于JS 中的赋值运算符是(重新)绑定还是突变?的主要内容,如果未能解决你的问题,请参考以下文章