【问题标题】:Why number are immutable in Javascript?为什么数字在 Javascript 中是不可变的?
【发布时间】:2018-03-05 15:55:16
【问题描述】:

我已经阅读了这里的问题和答案:

javascript numbers- immutable

但我还不够清楚为什么数字(原始类型)是不可变的?仅仅因为他们创建了一个新的引用但没有覆盖该值?

如果在每个assignemt 上都创建了一个新的引用

var x = 5;
x = 1;

我们会在下面的循环中有 100 次新的引用吗?

while (x < 101)
{
    x++;
}

这样有效吗?我觉得我看的不对。

【问题讨论】:

  • 如果数字 5 是可变的,这意味着什么?
  • 阅读您链接的问题中的答案:数字本身是不可变的(或者您可以说常量)。变量 x 是对数字/常数的引用。它还在那里说它在所有编程语言中都是相同的。否则,您可能会删除/覆盖数字并弄乱该语言可以执行的整个数学/计算。对吗?
  • 嗯,但是如果这个数字有点恒定,为什么我们可以重新分配它们的值? x= 5 然后 x=1。
  • 你不能。 x 是变量,51 是数字。数字是不可变的,使用允许重新分配的关键字声明的变量(在当前的 JS 中,varlet)不是。至于“它有效率吗?”:是的。处理器在硬件级别理解数字。并且您的代码在每次迭代中都有相同的引用 x 到不同的数字。
  • 没有对原始数字的引用。这些数字始终作为变量值存储在内存中的同一位置。

标签: javascript immutability


【解决方案1】:

老实说,我不太确定您期望什么样的答案,因为我不太了解您的困惑。但是我们开始了:

我们会在下面的循环中有 100 次新的引用吗?

变量只是值的容器。在底层,变量基本上只是内存地址或寄存器的标签。例如。变量x 可能指向寄存器R1

x++ 将简单地将存储在该寄存器中的数字增加1。让我们假设我们的寄存器看起来像这样:

R1: 5

递增后,可以是单个操作,比如ADD R1 1,我们会得到

R1: 6

即我们简单地用一个新值覆盖了以前的值。我们会多次这样做。


这样有效吗?我觉得我看的不对。

将一个数字加一是一项非常简单的操作。

当然,您可以在更高级别上实现可变数字,但它肯定不会让事情变得更高效或更简单。

可变性对于“单值”值没有多大意义,因为改变这样的值基本上意味着用“就地”不同的值替换它。

可变性对于由其他值(例如列表和字典)组成的值更有意义,其中一部分更改而另一部分保持不变。

此外,只有当语言具有引用类型数据类型时,可变性才显得相关。我的意思是多个变量可以保存对数据类型的相同值的引用。对象是 JavaScript 中的引用类型,它允许您这样做:

var a = {foo: 42};
var b = a;
b.foo = 21;
console.log(a);

如果数据类型不是引用类型,称为值类型(JavaScript 中的原始值),那么可变性就无关紧要,因为它与不变性没有区别。考虑以下具有可变值类型数字的假设场景:

var a = MutableNumber(42);
var b = a; // creates a copy of MutableNumber(42) because it's a value type
a.add(1);
console.log(a, b); // would log 43, 42

在这种情况下,两个变量不可能引用同一个可变数值,a.add(1) 与将新值分配给 a(即a = a + 1)没有区别。

【讨论】:

  • 那么,我们可以说数字是不可变的,因为每个变量(容器)都有不同的引用吗?编号不能通过引用修改。
【解决方案2】:

我能理解你的问题,问题是,在 while 循环中,每次 x 都会指向新值,而旧值将准备好进行垃圾回收,所以内存仍然被保留。

阅读此内容以获得更好的理解: https://developer.mozilla.org/en-US/docs/Glossary/Mutable

所以关于可变性,你的理解是正确的,变量引用了新值,旧值没有改变,因此原始值是不可变的。

参考:https://developer.mozilla.org/en-US/docs/Glossary/Primitive

【讨论】:

    【解决方案3】:

    变异是状态的变化,而数字(原始类型)是纯状态对象。对这种“对象”状态的任何突变实际上都是一个新数字。数字本身就像计算机内存单元中比特突变的标识符。

    因此数字是不可变的。与颜色或字符相同。

    同样值得澄清的是,对于任何给定变量,新数字将占用与旧数字相同的存储单元。真的要换旧的了。因此,不会对性能造成任何影响。

    【讨论】:

    • “纯状态对象”是什么意思?
    • 如果尝试将原始值描述为一个对象,该对象将没有任何方法,并且在表达式中使用时对象本身将评估为单个值的状态。
    【解决方案4】:

    我完全不明白,

    var a=12;
    a=45;
    

    我们可以推断;

    1.firstly解释器分配一块内存并将12定位到该区域。 实际上 (a) 是这个内存区域的标签。 2.than,解释器分配一个新的内存单元并将45定位到这个区域。 最后(a)与这个新的存储单元相关联。包含 12 的内存单元被垃圾收集器销毁。

    【讨论】:

    • 你说的“我们可以从;推断”是什么意思?谢谢
    • 文章1和2是真是假?
    【解决方案5】:

    原始值与引用:

    在 JavaScript 中 boolean、undefined、null、number、symbol、string 类型的值都是原始的。当您将它们分配给变量或将它们作为参数传递给函数时,它们总是被复制。 相比之下,对象有两个部分:对象(它的数据)存储在一块内存中,分配给变量的是指向该对象的引用。对象本身不会在赋值时被复制。

    因为当您将数字分配给变量时总是会复制数字,因此不可能更改数字并通过其他变量看到更改而不实际为该变量分配新值。 相反,当您更改对象上的字段时,指向该对象的所有变量都会看到该更改。

    让我们看一些例子:

    var a = 1;
    var b = a; //This creates a new copy of value 1
    console.log(a, b); // 1 1
    a = 2;
    console.log(a, b); // 2 1
    
    
    var obj_a = {attr: 1};
    var obj_b = obj_a; //This makes a new reference to the same object.
    console.log(obj_a, obj_b); // {'attr': 1} {'attr': 1}
    obj_b.attr = 2;
    console.log(obj_a, obj_b); // {'attr': 2} {'attr': 2}
    

    不可变对象:immutable.js

    immutable.js 之类的库提供的类型结合了原始类型和对象的属性:来自 immutable.js 的类型只要您不更改它们,它们的行为就与普通对象一样。当您更改不可变对象的属性时,会创建一个新对象,并且更改仅通过该新对象可见。好处是您节省了内存空间,并且您可以通过仅比较它们的引用来快速检查对象的相等性。您会得到一组行为类似于整数的类型,但您可以在其中存储更复杂的结构。

    【讨论】:

    • 通过引用传递和对对象使用引用是一回事。 JavaScript 是按值传递的,在对象的情况下,值是一个引用。您混淆了 values 的表示方式与变量和参数的评估方式。这是两个不同的东西。
    • 说字符串总是按值传递并因此被复制是不正确的。字符串实际上总是通过引用传递。
    • @MarcinMalinowski:见我之前的评论。 JavaScript 是按值传递的,该值可能是一个引用。不可变值的好处是它们可以被复制或被引用。实现可以为所欲为。
    • 在您的回复中阅读您的第一句话。
    • 明确地说,这就是通过引用的意思:var bar = 42; function foo(baz) { baz = 21; }; foo(bar);。调用 foo 后,bar 的值为 21,因为 baz 引用与 bar 相同的内存位置。但这不是它在 JavaScript 中的工作方式,无论变量的值如何。 stackoverflow.com/questions/373419/…
    猜你喜欢
    • 2011-04-28
    • 2016-09-28
    • 1970-01-01
    • 2013-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    相关资源
    最近更新 更多