JS基础精讲——也许你不懂的数据类型1

131 阅读4分钟

问题:在JavaScript中一共有几种数据类型?

大白:这我熟啊,不就是number、bigint、string、 boolean、 null、 undefined、 symbol、object、array、function一共十种。

能轻松列举出十种数据类型,不错,你是高手。

但高手中的高手会这么回答:

数据类型分为简单(原始)数据类型复杂数据类型,简单数据类型由:numeric、string、boolean、null、undefined、symbol六种,其中numeric就是将number和bigint归为一类叫做numeric,另外symbolbigint是es6新增的数据类型;复杂数据类型有:object、array、function,但array和function都是object的子类型。也就是说,数据类型一共有七种。

OIP-C.jpg

面试官:有点东西~

然而只是能列出多少种数据类型对面试来说是远远不够的,下面来讲讲关于数据类型我们还需要了解的知识点。

为什么要分简单数据类型和复杂数据类型

根据数据类型的特性内存分配方式,我们将它们分为简单数据类型(Primitive Types) 和复杂数据类型(Complex Types)。

JavaScript 的内存管理主要涉及两种内存区域:栈(Stack)堆(Heap) 。这两种内存区域分别用于存储不同类型的值,从而影响变量的分配和访问方式。

栈(Stack)

栈是一种线性的数据结构,遵循后进先出(LIFO, Last In First Out)的原则。在 JavaScript 中,栈主要用于存储简单数据类型(也称作原始数据类型)的值。

简单数据类型的值直接存储在栈中,因为它们占用的内存空间相对较小且固定。当一个简单数据类型的值被赋给另一个变量时,实际上是进行了值的复制。例如:

let a = 10;
let b = a; // b 的值是 10,a 和 b 分别在栈中存储了独立的值

堆(Heap)

堆是一种非线性的数据结构,用于存储复杂数据类型(也称作引用数据类型)的值。

这些类型的值通常较大且不固定,因此它们被存储在堆中。栈中只存储指向堆中实际数据的引用。当一个复杂数据类型的值被赋给另一个变量时,实际上是复制了这个引用,而不是值本身。例如:

let obj1 = { name: "Alice" };
let obj2 = obj1; // obj2 存储的是 obj1 的引用,两者指向同一个对象
obj2.name = "Bob"; // 修改 obj2 的值也会改变 obj1 的值
console.log(obj1.name); // 输出 "Bob"

内存分配过程

  1. 声明变量

    • 当声明一个变量时,JavaScript 引擎会在栈中为该变量分配一小块内存,用于存储变量的名称和类型信息。
  2. 赋值

    • 如果赋值的是一个简单数据类型,值会直接存储在栈中。
    • 如果赋值的是一个复杂数据类型,值会被存储在堆中,栈中存储的是指向堆中数据的引用。
  3. 传递参数

    • 当函数调用时,传递简单数据类型的参数会进行值的复制。
    • 传递复杂数据类型的参数会复制引用,而不是值本身。
  4. 垃圾回收

    • JavaScript 引擎会自动管理内存,通过垃圾回收机制释放不再使用的内存。对于栈中的简单数据类型,当变量超出作用域时,其占用的内存会被自动释放。
    • 对于堆中的复杂数据类型,当没有引用指向某个对象时,垃圾回收器会回收该对象占用的内存。

示例

// 简单数据类型
let num1 = 10;
let num2 = num1; // num2 的值是 10,num1 和 num2 分别在栈中存储了独立的值

// 复杂数据类型
let obj1 = { name: "Alice" };
let obj2 = obj1; // obj2 存储的是 obj1 的引用,两者指向同一个对象
obj2.name = "Bob"; // 修改 obj2 的值也会改变 obj1 的值
console.log(obj1.name); // 输出 "Bob"

// 函数调用
function changeValue(num, obj) {
    num = 20; // 修改 num 的值不会影响外部的 num1
    obj.name = "Charlie"; // 修改 obj 的值会影响外部的 obj1
}

changeValue(num1, obj1);
console.log(num1); // 输出 10
console.log(obj1.name); // 输出 "Charlie"

typeof

typeof 是 JavaScript 中的一个操作符,用于确定变量的数据类型。它可以返回一个表示变量类型的字符串。

let a = 1;
console.log(typeof a);
console.log(typeof "hello");
console.log(typeof true);
console.log(typeof 12n);
console.log(typeof Symbol());
console.log(typeof null);
console.log(typeof undefined);
console.log(typeof function () {});

运行结果:

ef2957eb-16d5-46ed-8949-c2b030dfb005.png

发现了吗?typeof null打印出来的结果是object,这其实是一个早期遗留下来的bug,并且当检查数组时,typeof [] 会返回 "object",这是因为数组在 JavaScript 中是对象的一种形式。如果需要特别检测一个值是否为数组,可以使用 Array.isArray() 方法。

小结

了解 JavaScript 的数据类型及其内存管理机制是每个开发者的基本功。通过合理利用简单数据类型和复杂数据类型,以及了解它们之间的区别,可以帮助我们编写出更加高效和易于维护的代码,下一篇我会详细介绍null、undefined、object以及es6新加入的symbol和bigint。

R-C.png

点个赞再走吧~