JavaScript中的原始数据类型与引用数据类型

473 阅读4分钟

数据类型可能是一个有点匪夷所思的概念。但作为程序员,我们每天都在使用数据类型--所以它们是我们应该了解的东西。

问题是,计算机是如何存储这些数据类型的?它不可能对每个数据类型都一视同仁。

在JavaScript中,数据类型被分成两类,计算机对每一类的处理都是不同的。我们有原始数据类型和引用数据类型。但这些是什么?为什么知道它们的区别很重要?这就是我们在这篇文章中要学习的内容。

JavaScript中的原始数据类型

这些数据类型非常简单,有时被视为编程语言的最低实现层次。它们不是对象,也没有方法。

这类数据类型的例子有数字、字符串、布尔运算、空和未定义:

Primitive data types

但你可能想知道字符串的情况,因为它们确实有方法。事实上,JavaSvript将原始字符串转换为字符串对象,这样就有可能使用字符串对象的方法。

在JavaScript中是如何处理原始数据类型的?

当你在JavaScript中声明一个原始数据类型时,它被存储在一个堆栈中。栈是一个简单的数据结构,计算机用它来快速存储和检索数据。

堆栈中的原始数据类型由你在程序中用于声明的变量名来识别。你每创建一个原始数据类型,数据就被添加到堆栈中。

为了实现这一点,假设我们声明一个变量,numOne ,并给它一个50的值。我们继续创建另一个变量,numTwo ,并给它分配同样的值50。所以两个变量都有相同的值。

在堆栈中发生的情况是,计算机为numOne ,并在堆栈中存储其分配的值。当创建numTwo ,计算机再次创建空间,并在堆栈中存储50。这两个变量被分配了相同的值并不重要:

Storing data on the stack

如果在编码过程中,我们决定将numOne 的值更新为例如100呢?这是否意味着numTwo 也会改变?答案是否定的。

因为numOnenumTwo 在堆栈中的存储方式不同,更新其中一个不会影响另一个。而且我们可以通过在代码编辑器中实际试用来实验。

numOne 记录到控制台将输出100,而记录numTwo 将输出50。所以,实际上,这两个变量彼此之间没有任何关系:

let numOne = 50;
let numTwo = numOne; //numTwo=numOne=50
numOne = 100;
console.log(numOne); //outputs 100
console.log(numTwo); //outputs 50

Updated stack

现在我们已经看到处理原始数据类型是多么容易,让我们看看类似的引用数据类型是如何工作的。

JavaScript中的引用数据类型

与原始数据类型不同,引用数据类型在本质上是动态的。也就是说,它们没有一个固定的大小。

它们中的大多数被认为是对象,因此有方法。这种数据类型的例子包括数组、函数、集合和所有其他类型的对象:

Reference data types

原始数据类型和引用数据类型之间有什么区别?

当计算机需要存储一个引用数据类型时,区别就出现了。当你创建一个变量并给它分配一个引用数据类型的值时,计算机并不直接在该变量中存储该数据类型(如原始类型的情况)。

你分配给该变量的是一个指针,指向内存中该数据类型的位置。令人困惑吗?我知道:

Reference data types

正如你在上面的图片中看到的,我们现在有两个数据结构。一个堆栈,和一个堆。例如,我们声明了一个对象。对象本身存储在堆上,它的指针存储在栈上。指针由对象的变量名识别,并指向该对象。

现在,我们可以创建一个变量,object1 ,并将一个对象分配给它。如果像以前一样,我们创建另一个变量object2 ,并把它分配给object1 。这是否意味着将在堆上创建另一个对象?答案是否定的。

因为该对象已经存在于堆中,object2object1 都将指向同一个对象。

当我们更新object1 ,另一个区别就出现了。如果我们把这两个变量都记录到控制台,我们会发现这个变化对它们都有影响。这是因为它们都指向堆中的同一个对象--更新一个变量当然会影响到另一个:

let object1 = {
name:'Bingeh',
age:18
};
let object2 = object1;

//updating object1,
object1.age = 20;

console.log(object2); //we see that object2 also updates the age attribute

Update on heap

总结

现在你知道了原始数据类型和引用数据类型之间的区别。知道这些这些区别有时很重要,因为你有时会得到 "空指针引用 "这样的错误,而你可能不知道原因。

Java开发者有时也会遇到这种情况,我希望这篇文章能帮助你解开疑惑。