JavaScript 中的数据类型分为基础类型和引用类型,它们在存储方式、赋值操作、比较方式等方面存在着显著的差异:
基础类型
- 定义及包含类型:JavaScript 的基础类型也称为原始类型,包括
undefined
、null
、boolean
、number
、string
和symbol
(ES6 新增)。这些类型代表了最基本的数据值,它们的值是不可变的,一旦创建就不能被修改。 - 存储方式:基础类型的值直接存储在栈内存中。栈内存是一种简单的数据结构,它以先进后出的方式存储数据,存储和访问速度都非常快。例如,当定义一个变量
let num = 5;
时,数字5
这个值就直接存储在栈内存中为变量num
所分配的空间里。 - 赋值操作:在进行赋值操作时,基础类型是按值传递的。也就是说,将一个基础类型变量的值赋给另一个变量时,会在新变量的内存空间中复制一份该值。例如,
let a = 10; let b = a;
此时b
会得到一个与a
相同的副本,后续对a
的修改不会影响到b
。 - 比较方式:基础类型在进行比较时,是比较它们的值是否相等。例如,
1 === 1
返回true
,'hello' === 'hello'
也返回true
。只要两个基础类型的值完全相同,它们的比较结果就是相等的。
引用类型
- 定义及包含类型:引用类型通常指的是对象类型,包括普通对象、数组、函数等。引用类型的值是可变的,并且可以包含多个属性和方法。
- 存储方式:引用类型的值存储在堆内存中,而在栈内存中只存储了指向该对象的指针。堆内存是一块较大的内存区域,用于存储动态分配的数据。当创建一个对象时,对象的实际数据会被存储在堆内存中,而在栈内存中会创建一个变量来存储指向该对象在堆内存中的地址。例如,
let obj = { name: 'John', age: 30 };
这里对象{ name: 'John', age: 30 }
的数据存储在堆内存中,而变量obj
在栈内存中存储的是指向该对象的指针。 - 赋值操作:引用类型的赋值操作是按引用传递的。当将一个引用类型变量赋给另一个变量时,实际上是将指向对象的指针复制给了新变量,两个变量最终指向的是同一个对象。例如,
let person1 = { name: 'Alice' }; let person2 = person1;
此时person1
和person2
都指向同一个对象,对其中一个变量所指向对象的属性进行修改,会影响到另一个变量所指向的对象。 - 比较方式:引用类型在进行比较时,比较的是它们在内存中的引用地址是否相同,而不是比较对象的内容是否相同。即使两个对象的属性和值完全相同,但如果它们是两个不同的对象实例,它们的比较结果也是不相等的。例如,
let obj1 = { x: 1 }; let obj2 = { x: 1 };
obj1 === obj2
返回false
。
理解 JavaScript 中的基础类型和引用类型的区别对于正确地编写代码和理解程序的行为非常重要。在实际开发中,需要根据具体的需求合理地选择和使用不同的数据类型,以避免出现一些意想不到的错误和问题。同时,在处理引用类型数据时,要特别注意对象的引用关系,避免因共享引用而导致的数据不一致等问题。