在计算机中,如果程序想要对某一块内存空间中的数据进行存储和操作,首先要明确的是该空间内数据的存储方式和操作方式。
举两个例子:
- 变量中存储的是数据本身还是数据在内存空间中的位置?这决定着这些数据的复制方式。
- 变量中的数据可以执行什么操作?是算术运算还是逻辑判断,抑或是文本处理?
这就需要我们对这些内存空间中的数据,即变量的值进行归类。例如将用来做算术运算的数据归为一类,将用于文本处理的数据归为另一类。在编程术语上,这些归类被人们约定俗成地称为【类型(type)】。
简而言之,变量的值所属的类型决定了该变量的存储形式及其可以执行的操作。下面从变量的数据类型开始介绍
具体到 JavaScript 语言中,变量的数据类型可以分成基本数据类型和对象类型两种。
JS 基本数据类型
以下是 JavaScript 所支持的 5 种基本数据类型。
Number
Number 是数字类型,这一类型的数据包括以下几种:
- 整数与浮点数:例如 0、1、−1、−0.25、3.14 等。
- 八进制数与十六进制数:例如 0377、0xff 等。
- 指数:即用科学记数法表示的数字,例如 1e+2、10e+3 等。
- Infinity 与 NaN:这是 JavaScript 中的两个特殊数字。
关于 Infinity 和 NaN:
- Infinity 表示的是一个超出 JavaScript 接受范围的数字,相当于 JavaScript 世界中的“无穷大”,和数学中有正无穷大和负无穷大一样,这类值也是有 Infinity 和 −Infinity 两种的。
- 而 NaN 则表示的是一种不符合规范但仍属于数字类型的数字,例如当一个数字与一个字符串相乘时,结果就会是一个 NaN。
String
String 是字符串类型,这一类型的数据主要指的是被反引号、单引号或双引号所引起来的、由任意个字符组成的字符序列,例如 a、123、”one”、”one two three” 等。
另外,出于代码可读性方面的考虑,建议读者在字符串的表示风格上保持一致,不要时而用单引号,时而用双引号。当然,ES6 新增的反引号表示的字符串形式比较特殊,它主要用于建立模板字符串,通常只有在特定场景中才会用到它。
例如,当我们需要将某个变量的值嵌入某个 HTML 标签中时,可以这样做:
const name = 'owlman';
console.log('<h1> ${ name }</h1>'); // 输出 <h1> owlman </h1>
在模板字符串中,我们只需要使用${[变量名]}
这样的语法就可以将现有变量的值嵌入字符串中,这里的[变量名]
可以是任何已在别处定义的变量的名称。这样就避免了一系列拼接字符串的麻烦,既简洁又不易出错。
Boolean
Boolean 是布尔类型,这一类型的数据只有 true 和 false 两种值,主要用于关系运算和逻辑运算。
undefined
这是 JavaScript 中的一个特殊值,当我们访问一个不存在的变量或未被初始化的变量时,程序就会返回一个 undefined 值。
null
这也是 JavaScript 中的一个特殊值,通常是指没有值或值为空,不代表任何东西。
null 与 undefined 最大的不同在于,被赋予 null 的变量会被认为是初始化了的,只不过它是个空值。
在 JavaScript 中,任何不属于上述 5 种基本数据类型的值都会被视为对象,某些运行环境甚至将 null 值也视为一个对象。
作为一种动态类型的脚本语言,JavaScript 的数据类型是直接与“值”,而不是与变量相关联的。这也就意味着,在 JavaScript 代码的执行过程中,变量的类型是可以随着变量的值而变化的。
例如,如果我们在代码中定义了一个名为 x 的变量,x 是可以初始值为数字,然后在执行过程中被重新赋予其他类型的值的,JavaScript 的运行环境会负责自动识别变量的类型。
下面,我们可以用类型操作符 typeof 来验证一下(该操作符会返回一个代表数据类型的字符串),打开 node 解释器并设为交互模式,执行下面图片的测试。
![图片[1]|JavaScript基本数据类型详解](https://www.91yiqixue.com/wp-content/uploads/2022/03/js数据类型.gif)
JS 存储类型
前面我们讨论的是变量“值”所属的数据类型,它决定的是这些值可执行的操作。但在 JavaScript 中,变量只负责存储数据,与数据类型并没有直接的关联,这是它与 Java、C/C++ 这些强类型语言的一个重大区别。那么,变量在存储上有没有分类型呢?
答案是有,变量的存储类型决定了变量值的存储方式。根据 ECMAScript 标准的规定,变量的存储方式可分为以下两种类型。
原始类型
在这一类型的存储方式下,变量的值往往会直接存储在变量所在栈空间中。由于这种方式所占的内存空间是固定的,所以通常用来存储一些简单且需要快速存取的数据。
引用类型
在这一类型的存储方式下,变量的值往往会被分配在堆空间中,然后将其在堆空间中的位置存储在变量中,通常用来存储一些复杂且内存开销较大的数据。
那么,当我们为一个变量赋值时,该如何判断该值的存储类型呢?答案很简单,在 JavaScript 中,只有基本数据类型是以原始值的方式存储的。也就是说,除了 Number、String、Boolean、undefined 和 null 这 5 种基本数据类型,其他的值都是以引用的形式存储的。
请记住,如果某个数据是以引用的方式来存储的,则说明这个数据所占用的内存空间大小是不固定的,因此需要让 JavaScript 解释器在堆空间中为其分配内存。如果将其分配在栈空间中,其不固定的内存空间势必会降低数据的存取速度。
所以,我们选择了将该数据在堆空间中的位置存储在变量所在的栈空间中,而位置信息的大小是固定的,把它存储在栈中对程序的执行性能无任何负面影响。