原文:Mutable and immutable in JavaScript
https://blog.devgenius.io/mutable-and-immutable-in-javascript-78a3cbc6187c
根据 Mozilla 的定义-
可变(Mutable)是一种可以更改的变量。 在 JavaScript 中,只有对象和数组是可变的,原始值不可变。
可变对象是在创建后可以修改其状态的对象。
不可变对象一旦创建,其状态无法更改。
让我们分解以上定义
JavaScript 中有两种数据类型——原始类型(值类型)和非原始类型(引用类型)。
值类型
值类型存储在我们内存的栈中。 栈只是具有“LIFO”(后进先出)数据结构的数据堆栈。 它没有太多空间(与其他数据结构相比),但由于它的工作方式,它的访问速度非常快。
当在内存中存储一个值类型时,它会将一个元素添加到栈顶部,其中包含新创建的变量的值。 当创建一个新变量并将第一个变量分配给新变量时,它会在栈顶添加一个新元素,其中包含新变量的值(即第一个被创建的变量的值)。
通过创建
var name = "Maya";
var newName = name;
第一个变量 — name
与变量的值一起进栈。 然后,newName
与变量的值一起进入栈中的新内存位置。
引用类型
引用类型存储在堆上。 堆与栈无关,它没有存储数据的顺序。你可以将其视为随机存储数据,其中每个数据都有自己的地址。 堆的访问速度较慢,但空间更大,因为它处理更复杂的变量。
在内存中存储引用类型时,会在栈顶添加一个新元素,其值是一个指向已存储在堆上的对象地址的指针/引用。
通过创建
var Person = {name: "Maya", age: "29"}
var newPerson = Person;
一个新元素进栈,其值即一个指针/引用指向已存储在堆上的 Person
对象。
当创建一个 newPerson
对象并将前一个Person
对象赋给它时,它会在栈顶添加一个新元素,该元素的值是指向已存储在堆上的Person
对象的指针/引用。
让我们看一些代码
让我们创建一个以字符串为值的变量。 然后,我们创建一个新变量并将第一个变量分配给它。 然后,我们将更改第一个变量的值。 我们将在创建每个变量后打印它。
var name = 'Maya';
console.log(name);
var newName = name;
console.log(newName);
name = 'Joe';
console.log(newName);
毫不奇怪,我们将在控制台中看到以下输出。
现在,让我们创建一个对象变量。 然后,我们将创建一个新的对象变量并将第一个对象分配给它。 然后,我们将更改第一个对象的数据。 同样,我们将在创建每个变量后打印它。
var person = {name:'Maya', age:29};
console.log(person);
var newPerson = person;
console.log(newPerson);
person.name = 'Joe';
console.log(newPerson);
这一次,我们将在控制台中看到
可变和不可变
你是否看到更改值类型 name
不会影响 newName
,但更改 Person
对象时会影响 newPerson
?
发生这种情况是因为数据的存储方式。
每次创建值类型时,都会有一个新元素进入栈顶并存储该变量的数据。 另一方面,当创建一个引用类型时,一个新元素进入栈顶,但这一次,它存储的是指向存储在堆中的对象的地址位置的引用/指针。 然后,当我们将创建的对象分配给一个新的对象变量时,一个新元素进入栈顶,但是具有指向第一个对象的相同引用/指针。
因此,当更改已创建对象的数据时,指向堆上相同地址位置的所有其他对象也被更改。
考虑到这一点,我们可以说值类型是不可变的,而引用类型是可变的。