几分钟理解js数据类型和一切皆对象的特性

128 阅读5分钟

avaScript 是一种动态类型、弱类型(或称为松散类型)的脚本语言,这意味着你不需要显式声明变量的类型,JavaScript 会根据赋值自动推断变量的类型。JavaScript 中的数据类型可以大致分为两类:简单数据类型(也称为原始数据类型)和复杂数据类型(也称为引用数据类型)。

简单数据类型(Primitive Types)

简单数据类型直接存储在栈(stack)内存中,并且它们的值是不可变的。当你从一个变量向另一个变量复制一个原始值时,原始值会被复制到新变量的位置。

  1. Number:包括整数和浮点数,以及特殊的值 NaN(Not-a-Number,非数字值)和 Infinity(无穷大)。
  2. BigInt:表示任意精度的整数。
  3. String:用于表示文本数据,即一系列字符。
  4. Boolean:表示两个值之一:true 或 false。
  5. Undefined:表示变量未定义时的值。
  6. Null:表示一个空值,或一个不存在的对象。尽管 typeof null 返回 "object",但 null 被认为是原始值。
  7. Symbol:表示唯一的标识符,通过 Symbol 函数创建。

复杂数据类型(Reference Types)

复杂数据类型(或引用类型)存储在堆(heap)内存中。当你从一个变量向另一个变量复制引用类型的值时,复制的是引用,即内存地址,而不是实际的值。因此,两个变量实际上引用的是同一个对象。

  1. Object:JavaScript 中所有非原始值都被称为对象。对象可以包含多个属性,每个属性都有一个名称和值。JavaScript 提供了几种内置对象类型,如数组、函数、日期等。

    • 数组(Array) :一种特殊的对象类型,用于存储一系列有序的值。数组的每个位置都有一个索引,从 0 开始。
    • 函数(Function) :在 JavaScript 中,函数也是对象。函数对象可以包含属性和方法,并且可以像其他对象一样被传递和操作。函数是 JavaScript 中的一等公民,意味着函数可以作为参数传递给其他函数,也可以从函数中返回。

内存分配机制

  • 栈内存(Stack Memory) :用于存储简单数据类型的值。栈内存的特点是访问速度快,但容量有限。
  • 堆内存(Heap Memory) :用于存储复杂数据类型的对象。堆内存的特点是访问速度相对较慢,但容量大,可以动态分配和释放内存。

拷贝与引用

  • 拷贝(Copy) :对于简单数据类型,当你从一个变量复制另一个变量时,实际上是在复制值。
  • 引用(Reference) :对于复杂数据类型,当你从一个变量复制另一个变量时,实际上是在复制引用(即内存地址)。因此,两个变量都指向同一个对象。

实例展示

image.png

显然```let obj2=obj1 ;obj2.name="二壮";```` obj2 并不是继承 obj1 的属性,而是引用了同一个对象。这意味着 obj1 和 obj2` 指向内存中的同一个位置,它们实际上是同一个对象的两个不同引用。

25f8a84f30c85b39ad5639e7136291b.png 28f0f17b42367ae2f91b97414f16f13.png

typeof 运算符

typeof 运算符用于确定一个变量的类型。然而,需要注意的是,typeof null 返回的是 "object",这是一个历史遗留的 bug。为了准确判断变量的类型,尤其是区分对象和原始值,可以使用 Object.prototype.toString.call() 方法。

“一切皆对象”的含义

虽然JavaScript中有基本数据类型和对象类型之分,但基本数据类型在特定情况下会被当作对象来处理。这是通过“包装对象”(Wrapper Objects)机制实现的。

当基本数据类型需要被当作对象来操作时(例如调用方法),JavaScript会自动将其包装成对应的对象类型。例如:

	let str = "Hello";

	console.log(str.toUpperCase()); // 输出:HELLO

在这个例子中,虽然str是一个基本数据类型String,但它可以调用字符串对象的方法toUpperCase()。这是因为JavaScript在后台将str临时包装成了一个String对象,然后调用该对象的方法。

特殊值nullundefined

虽然“一切皆对象”是一个有用的概念,但有两个值除外:nullundefined

  • null是一个空值,表示一个空对象引用,但它本身不是对象。
  • undefined表示变量未定义或未赋值的状态,它也不是对象。

总结

JavaScript 的数据类型系统虽然相对简单,但通过灵活使用,可以实现复杂的数据结构和功能。理解不同类型之间的区别和内存分配机制,有助于编写更高效、更可靠的代码。JavaScript中的“一切皆对象”概念有助于理解语言的底层机制,尤其是在处理基本数据类型和对象类型之间的转换时。尽管严格来说,基本数据类型不是对象,但JavaScript通过包装对象机制允许它们在某些情况下表现得像对象。这种设计使得JavaScript在编程时更加灵活和统一。对于高级开发者来说,深入理解 JavaScript 的类型系统和内存管理,是提升编程能力和性能优化的关键。