面经一:javascript中的数据类型?存储上的差别?

66 阅读4分钟

在 JavaScript 中,数据类型可以分为两大类:原始数据类型(Primitive Types)引用数据类型(Reference Types) 。它们在存储方式、内存管理和操作上存在显著差异。

1. 原始数据类型(Primitive Types)

原始数据类型是 JavaScript 中的基本数据类型,包括以下几种:

  • String:字符串,由字符组成的序列,例如 "Hello"
  • Number:数字,包括整数和浮点数,例如 423.14
  • Boolean:布尔值,只有两个值:truefalse
  • Undefined:表示变量已声明但未初始化,即没有赋予具体的值。
  • Null:表示故意赋予的空值。
  • Symbol(ES6 新增):表示一个唯一的、不可变的数据类型,常用于对象属性的键。
  • BigInt(ES2020 新增):表示大于 2^53 - 1 的整数。

原始数据类型的存储特点:

  1. 存储位置
let a = 10; // 数字存储在栈内存
let b = "Hello"; // 字符串存储在栈内存
    • 原始数据类型的数据直接存储在栈内存中。栈内存的特点是访问速度快,但容量有限。
    • 当你声明一个原始类型的变量时,它的值会直接存储在变量访问的位置。
  1. 复制操作
let a = 10;
let b = a; // b 是 a 的副本
b = 20;
console.log(a); // 输出 10,a 的值没有改变
    • 当你对原始数据类型进行赋值操作时,实际上是将值的副本复制到新的变量中。这意味着两个变量是完全独立的,修改一个不会影响另一个。
  1. 比较操作
let a = 10;
let b = 10;
console.log(a === b); // true,因为值相同
    • 比较两个原始类型的值时,比较的是它们的实际值。

2. 引用数据类型(Reference Types)

引用数据类型包括所有非原始类型的对象,例如:

  • Object:普通对象,例如 { name: "Alice", age: 25 }
  • Array:数组,例如 [1, 2, 3]
  • Function:函数,例如 function sayHello() { console.log("Hello"); }
  • 其他复杂类型:如 DateRegExp 等。

引用数据类型的存储特点:

  1. 存储位置
let obj = { name: "Alice" }; // 对象存储在堆内存,obj 存储的是引用
    • 引用数据类型的数据存储在堆内存中。堆内存的特点是容量大,但访问速度相对慢一些。
    • 当你声明一个引用类型的变量时,变量存储的是指向堆内存中实际数据的引用(地址),而不是数据本身。
  1. 复制操作
let obj1 = { name: "Alice" };
let obj2 = obj1; // obj2 和 obj1 指向同一个对象
obj2.name = "Bob";
console.log(obj1.name); // 输出 "Bob",obj1 的值也被修改了
    • 当你对引用数据类型进行赋值操作时,复制的是引用(地址),而不是实际的数据。这意味着两个变量指向同一个对象,修改一个会影响另一个。
  1. 比较操作
let obj1 = { name: "Alice" };
let obj2 = { name: "Alice" };
console.log(obj1 === obj2); // false,因为它们是两个不同的对象,引用地址不同
    • 比较两个引用类型的值时,比较的是它们的引用地址,而不是实际内容。

3. 存储上的差别总结

特点原始数据类型引用数据类型
存储位置存储在栈内存中存储在堆内存中,变量存储引用
复制操作复制值的副本复制引用地址,指向同一个对象
比较操作比较实际值比较引用地址
内存释放当变量超出作用域时,栈内存自动释放当没有引用指向对象时,由垃圾回收机制释放堆内存

4. 垃圾回收机制

  • 对于引用数据类型,JavaScript 使用垃圾回收机制(GC)来管理内存。当一个对象没有任何引用指向它时,垃圾回收器会将其占用的堆内存释放掉。
  • 原始数据类型存储在栈内存中,当变量超出作用域时,栈内存会自动释放。

5. 性能和内存优化建议

  1. 合理使用数据类型
    • 如果只需要存储简单的值,优先使用原始数据类型,因为它们访问速度快,占用内存少。
    • 如果需要存储复杂的数据结构或需要多个属性和方法,使用引用数据类型。
  1. 避免不必要的引用
    • 如果不再需要某个引用类型的对象,可以手动将其引用设置为 null,帮助垃圾回收器更快地释放内存。
  1. 注意内存泄漏
    • 避免创建不必要的全局变量,因为它们会一直占用内存,直到页面关闭。
    • 对于大型数据结构,如数组或对象,使用完后及时释放引用。

总之,理解 JavaScript 中原始数据类型和引用数据类型的区别,可以帮助你更好地管理内存,优化代码性能,避免常见的错误和内存泄漏问题。