Javascript 不可变是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3200211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:38:58  来源:igfitidea点击:

What does immutable mean?

javascriptvariablesimmutability

提问by alex

If a string is immutable, does that mean that.... (let's assume JavaScript)

如果一个字符串是不可变的,这是否意味着......(让我们假设 JavaScript)

var str = 'foo';

alert(str.substr(1)); // oo

alert(str); // foo

Does it mean, when calling methods on a string, it will return the modified string, but it won't change the initial string?

这是否意味着,在字符串上调用方法时,它会返回修改后的字符串,但不会更改初始字符串?

If the string was mutable, does that mean the 2nd alert()would return ooas well?

如果字符串是可变的,这是否意味着第二个alert()也会返回oo

回答by kemiller2002

It means that once you instantiate the object, you can't change its properties. In your first alert you aren't changing foo. You're creating a new string. This is why in your second alert it will show "foo" instead of oo.

这意味着一旦你实例化了对象,你就不能改变它的属性。在您的第一个警报中,您没有更改 foo。您正在创建一个新字符串。这就是为什么在您的第二个警报中它会显示“foo”而不是 oo。

Does it mean, when calling methods on a string, it will return the modified string, but it won't change the initial string?

这是否意味着,在字符串上调用方法时,它会返回修改后的字符串,但不会更改初始字符串?

Yes. Nothing can change the string once it is created. Now this doesn't mean that you can't assign a new string object to the strvariable. You just can't change the current object that str references.

是的。字符串一旦创建就无法更改。现在这并不意味着您不能为str变量分配一个新的字符串对象。您只是无法更改 str 引用的当前对象。

If the string was mutable, does that mean the 2nd alert() would return oo as well?

如果字符串是可变的,这是否意味着第二个 alert() 也会返回 oo ?

Technically, no, because the substring method returns a new string. Making an object mutable, wouldn't change the method. Making it mutable means that technically, you could make it so that substring would change the original string instead of creating a new one.

从技术上讲,不会,因为 substring 方法返回一个新字符串。使对象可变,不会改变方法。使其可变意味着从技术上讲,您可以使子字符串更改原始字符串而不是创建新字符串。

回答by deceze

On a lower level, immutability means that the memory the string is stored in will not be modified. Once you create a string "foo", some memory is allocated to store the value "foo". This memory will not be altered. If you modify the string with, say, substr(1), a new string is created and a different part of memory is allocated which will store "oo". Now you have two strings in memory, "foo"and "oo". Even if you're not going to use "foo"anymore, it'll stick around until it's garbage collected.

在较低级别上,不变性意味着存储字符串的内存不会被修改。创建字符串后"foo",会分配一些内存来存储该值"foo"。这个记忆不会被改变。如果您修改字符串,例如,substr(1)将创建一个新字符串并分配内存的不同部分,该部分将存储"oo". 现在您在内存中有两个字符串,"foo"并且"oo". 即使你"foo"不再使用它,它也会一直存在,直到它被垃圾收集。

One reason why string operations are comparatively expensive.

字符串操作相对昂贵的原因之一。

回答by SoftwareGeek

Immutable means that which cannot be changed or modified.

不可变意味着不能改变或修改。

So when you assign a value to a string, this value is created from scratch as opposed to being replaced. So everytime a new value is assigned to the same string, a copy is created. So in reality, you are never changing the original value.

因此,当您为字符串赋值时,该值是从头开始创建的,而不是被替换。因此,每次将新值分配给同一个字符串时,都会创建一个副本。所以实际上,你永远不会改变原始值。

回答by Brian S

I'm not certain about JavaScript, but in Java, strings take an additional step to immutability, with the "String Constant Pool". Strings can be constructed with string literals ("foo") or with a Stringclass constructor. Strings constructed with string literals are a part of the String Constant Pool, and the same string literal will always be the same memory address from the pool.

我不确定 JavaScript,但在 Java 中,字符串通过“字符串常量池”向不变性迈出了额外的一步。字符串可以用字符串文字 ( "foo") 或String类构造函数构造。使用字符串字面量构造的字符串是字符串常量池的一部分,并且相同的字符串字面量将始终来自池中的相同内存地址。

Example:

例子:

    String lit1 = "foo";
    String lit2 = "foo";
    String cons = new String("foo");

    System.out.println(lit1 == lit2);      // true
    System.out.println(lit1 == cons);      // false

    System.out.println(lit1.equals(cons)); // true

In the above, both lit1and lit2are constructed using the same string literal, so they're pointing at the same memory address; lit1 == lit2results in true, because they are exactly the same object.

在上面,lit1lit2都是使用相同的字符串字面量构造的,因此它们指向相同的内存地址;lit1 == lit2结果为true,因为它们是完全相同的对象。

However, consis constructed using the class constructor. Although the parameter is the same string constant, the constructor allocates new memory for cons, meaning consis not the same object as lit1and lit2, despite containing the same data.

但是,cons是使用类构造函数构造的。尽管参数是同一个字符串常量,但构造函数为 分配了新内存,尽管包含相同的数据,但这cons意味着conslit1和不是同一个对象lit2

Of course, since the three strings all contain the same character data, using the equalsmethod will return true.

当然,由于三个字符串都包含相同的字符数据,使用该equals方法会返回true。

(Both types of string construction are immutable, of course)

(当然,两种类型的字符串构造都是不可变的)

回答by Nataraj

Immutable means the value can not be changed. Once created a string object can not be modified as its immutable. If you request a substring of a string a new String with the requested part is created.

不可变意味着值不能改变。字符串对象一旦创建就不能修改为不可变的。如果您请求字符串的子字符串,则会创建具有请求部分的新字符串。

Using StringBuffer while manipulating Strings instead makes the operation more efficient as StringBuffer stores the string in a character array with variables to hold the capacity of the character array and the length of the array(String in a char array form)

在操作字符串时使用 StringBuffer 可以使操作更高效,因为 StringBuffer 将字符串存储在带有变量的字符数组中,以保存字符数组的容量和数组的长度(字符数组形式的字符串)

回答by ahmed khattab

The text-book definition of mutability is liable or subject to change or alteration. In programming, we use the word to mean objects whose state is allowed to change over time. An immutable value is the exact opposite – after it has been created, it can never change.

可变性的教科书定义可能会发生变化或变更。在编程中,我们使用这个词来表示其状态可以随时间改变的对象。不可变值恰恰相反——它被创建后,就永远不会改变。

If this seems strange, allow me to remind you that many of the values we use all the time are in fact immutable.

如果这看起来很奇怪,请允许我提醒您,我们一直使用的许多值实际上是不可变的。

var statement = "I am an immutable value";
var otherStr = statement.slice(8, 17);

I think no one will be surprised to learn that the second line in no way changes the string in statement. In fact, no string methods change the string they operate on, they all return new strings. The reason is that strings are immutable – they cannot change, we can only ever make new strings.

我想没有人会惊讶地发现第二行不会改变语句中的字符串。事实上,没有任何字符串方法会改变它们操作的字符串,它们都返回新的字符串。原因是字符串是不可变的——它们不能改变,我们只能创建新的字符串。

Strings are not the only immutable values built into JavaScript. Numbers are immutable too. Can you even imagine an environment where evaluating the expression 2 + 3 changes the meaning of the number 2? It sounds absurd, yet we do this with our objects and arrays all the time.

字符串并不是 JavaScript 中唯一的不可变值。数字也是不可变的。你能想象这样一个环境,其中计算表达式 2 + 3 会改变数字 2 的含义吗?这听起来很荒谬,但我们一直在用我们的对象和数组来做这件事。

回答by Leniel Maccaferri

From strings to stacks... a simple to understand example taken from Eric Lippert's blog:

从字符串到堆栈……一个简单易懂的例子,取自Eric Lippert 的博客

Path Finding Using A* in C# 3.0, Part Two...

在 C# 3.0 中使用 A* 进行路径查找,第二部分...

A mutable stack like System.Collections.Generic.Stack is clearly not suitable. We want to be able to take an existing path and create new paths from it for all of the neighbours of its last element, but pushing a new node onto the standard stack modifies the stack. We'd have to make copies of the stack before pushing it, which is silly because then we'd be duplicating all of its contents unnecessarily.

Immutable stacks do not have this problem. Pushing onto an immutable stack merely creates a brand-new stack which links to the old one as its tail. Since the stack is immutable, there is no danger of some other code coming along and messing with the tail contents. You can keep on using the old stack to your heart's content.

像 System.Collections.Generic.Stack 这样的可变堆栈显然不合适。我们希望能够采用现有路径并从中为其最后一个元素的所有邻居创建新路径,但是将新节点推入标准堆栈会修改堆栈。我们必须在推送之前制作堆栈的副本,​​这很愚蠢,因为那样我们会不必要地复制它的所有内容。

不可变栈没有这个问题。推入一个不可变的堆栈只会创建一个全新的堆栈,该堆栈链接到旧堆栈作为其尾部。由于堆栈是不可变的,因此不会有其他代码出现并弄乱尾部内容的危险。您可以继续使用旧堆栈来满足您的需求。

To go deep on understaning immutability, read Eric's posts starting with this one:

要深入了解不变性,请阅读 Eric 的帖子,从以下开始:

Immutability in C# Part One: Kinds of Immutability

C# 中的不变性第 1 部分:不变性的种类

回答by Rick

One way to get a grasp of this concept is to look at how javascript treats all objects, which is by reference. Meaning that all objects are mutableafter being instantiated, this means that you can add an object with new methods and properties. This matters because if you want an object to be immutable the object can not change after being instantiated.

掌握这个概念的一种方法是查看 javascript 如何处理所有对象,这是通过引用。这意味着所有对象在实例化后都是可变的,这意味着您可以添加具有新方法和属性的对象。这很重要,因为如果您希望对象不可变,则该对象在实例化后无法更改。