理解Javascript不可变变量

时间:2013-04-20 01:13:05

标签: javascript

我试图理解Javascript不可变变量的含义。如果我能做到:

var x = "astring";
x = "str";
console.log(x); //logs str` , then why it is immutable?

我能想到的唯一答案(从CI的一点点知道)是var x是指向具有值“astring”的内存块的指针,在第二个语句之后它指向另一个具有值“ STR”。是这样的吗?

还有一个额外的问题:我对Javascript的值类型感到困惑。引擎盖下的所有变量都是对象吗?偶数和字符串?

5 个答案:

答案 0 :(得分:50)

是不可变的; 变量不是;他们提到了他们(原始)的价值观。

三种基本类型 string,number和boolean 具有相应的类型,其实例是对象: String,Number,Boolean
它们有时被称为 wrapper types

以下值为primitive

  • 字符串:“你好”
  • 数字:6,3.14(JavaScript中的所有数字都是浮点数)
  • 布尔:真,假
  • null:通常明确分配
  • undefined:通常是默认(自动分配)值

所有其他值都是对象,包括基元的包装器。

所以:

  • 默认情况下对象是可变的
  • 对象具有唯一标识,并通过引用进行比较
  • 变量持有对象的引用
  • 原语是不可变的
  • 基元按价值进行比较,它们没有个人身份

您可能会发现The Secret Life of JavaScript Primitives一个很好的解释。

此外,在ES6中有一个新的const关键字,它创建一个只读的命名常量,它不能通过赋值更改值,也不会在脚本运行时重新声明。

希望这有帮助!

答案 1 :(得分:15)

首先,在C中“字符串是一个字符数组,其中last elem ='\ 0'”。它们是可变的 如果你在C中声明并初始化一个字符串,如下所示:

char str[] = "Foo";

你基本上做的是保留4个字节(可能是8位字节,如果它伤害了你,不要介意这个)。 str这个词用作指向这个数组的第一个elem的指针。所以,如果你喜欢这样:

str[0] or *(str) = 'G'

然后它将改变该地址的值而不是创建新数组。您可以通过打印出str的地址来验证它。在这两种情况下它都是一样的。

现在,如果JavaScript字符串是基本类型。字符串上的所有操作都是通过值而不是通过引用来完成的。所以,这样做会产生真实的效果。

var str1 = "foo";
var str2 = "foo";
str1 === str2; => true

字符串的初始化要求缓冲区适合“foo”并将名称str1绑定到它。使它们不可变的原因是你不能改变那个缓冲区。所以,你不能这样做:

str1[0] = 'G'

执行此命令不会在非严格模式下产生警告或错误,但不会更改str1。您可以通过

进行验证
console.log(str1) => "foo"

但如果你喜欢这样:

str1 = "goo"

你实际上在做的是你要求一个新的缓冲区以适应“goo”并将标识符str1绑定到它。包含“foo”的旧缓冲区没有变化。

那么,“foo”会发生什么?

Java Script有一个自动垃圾收集器。当它看到一些内存不再可以被任何标识符引用时......或者它认为该内存是免费的。

同样的数字,布尔人。 现在,关于包装器对象! 每当您尝试使用以下字符串访问属性时:

str1.length;

它使用String类创建一个新对象并在string上调用方法。一旦函数调用返回,对象就会被销毁。 以下代码进一步解释:

var str = "nature"; 
str.does = "nurtures"; //defining a new property; 
console.log(str.does) => undefined

因为对象已被破坏。 试试这个!

var str = new String("Nature");
str.does = "nurtures";
console.log(str) =>  ??

这个str真的是一个对象......

结论:在C中,在单个作用域中,变量名称用作指针。所以,int,float,string都是可变的。但是在Java Script中,基本类型变量名称用作值而不是引用

参考文献:C ++ primer plus,Java Script The Definitive Guide,C by Stephen Kochan

答案 2 :(得分:5)

你是对的。字符串(和数字)在java脚本(以及许多其他语言)中是不可变的。变量是对它们的引用。当您“更改变量的值”时,您正在更改变量引用的字符串(或其他内容),而不是值本身。

答案 3 :(得分:2)

我认为许多新程序员认为不可变性意味着原始值不能通过重新分配来改变。

var str = "testing";
var str = "testing,testing";
console.log(str); // testing, testing

var fruits = ["apple", "banana", "orange"];

fruits[0] = "mango";

console.log(fruits); //["mango", "banana", "orange"]

与可变和不可变类型相关联的值可以通过重新分配来更改,因为上面的示例包含字符串和数组。 但是,这些数据类型具有相关的函数(方法),用于操作属于每种数据类型的值。这是看到可变性/不变性的地方。由于数组是可变的,因此数组方法的任何操作都会直接影响数组。例如,

var fruits = ["mango","banana", "orange"];
fruits.pop(); 
console.log(fruits) //["mango", "banana"]


The array.pop() method deleted "orange" from the original fruits array.
But with strings for example,


var name = "Donald Trump";
name.replace("Donald", "President");
console.log(name)//Donald Trump

the original string remains intact!

Immutability不允许通过字符串方法更改原始字符串。相反,如果将方法操作分配给变量,则该方法会生成一个新字符串:

var name = "Donald Trump";
var newName = name.replace("Donald", "President");
console.log(newName);//President Trump

答案 4 :(得分:1)

让我们先了解一下,

let firstString = "Tap";

console.log(firstString);  //Output: Tap 

firstString[0] = "N";

console.log(firstString)   //Output: Tap

在这里我们可以看到不变的效果