繁体   English   中英

理解 Javascript 不可变变量

[英]Understanding Javascript immutable variable

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

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

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

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

是不可变的; 变量不是; 他们拥有对其(原始)值的引用。

字符串,数字和布尔值这三种原始类型具有对应的类型,其实例是对象: 字符串,数字,布尔值
它们有时称为包装器类型

以下是原始值:

  • 字符串:“ hello”
  • 数字:6、3.14(JavaScript中的所有数字均为浮点数)
  • 布尔值:true,false
  • null:通常显式分配
  • 未定义:通常为默认值(自动分配)

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

所以:

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

您可能会发现JavaScript原语的秘密生活是一个很好的解释。

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

希望这可以帮助!

首先,在C中,“字符串是最后一个elem ='\\ 0'的字符数组”。 它们是可变的。
如果像这样在C中声明和初始化字符串:

char str[] = "Foo";

您基本上要做的是保留4个字节(可能是8位字节,如果这对您造成伤害,请不要介意)。 单词str用作此数组的第一个元素的指针。 因此,如果您这样做:

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;

JavaScript会使用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 ++入门指南,Java脚本权威指南,Stephen Kochan的C

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

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

 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! 

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

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

在这里先了解一下,

let firstString = "Tap";

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

firstString[0] = "N";

console.log(firstString)   //Output: Tap

这就是我们可以看到不可变效果的地方

这个定义中的不变性是历史性的。 它附属于可以用其他编程语言完成的工作。

我认为这是首先要理解的。 对于只使用过 JavaScript 的程序员来说,这个问题可能看起来很荒谬或不必要的迂腐。 将原语描述为不可变就像将冰淇淋描述为不能跳跃一样。 为什么我觉得可以? 只有与其他历史编程语言相比,在处理原始类型时才会明显缺乏可变性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM