JavaScript中基本类型存栈、赋值复制值、不可变;引用类型存堆、赋值复制地址、可变;检测类型宜用Object.prototype.toString.call()。

区分 JavaScript 中的基本数据类型和引用数据类型,关键不在“叫什么”,而在于“怎么存、怎么传、怎么变”。掌握三点就能快速判断:内存位置、赋值行为、可变性。
看内存存储位置
基本类型(Undefined、Null、Boolean、Number、String、Symbol、BigInt)的值直接存在栈内存里,变量名就指向那个具体的值。比如 let a = "hello",栈中就实实在在存着字符串 "hello"。
引用类型(Object 及其所有子类:Array、Function、Date、RegExp、Map、Set 等)的实际数据存在堆内存,变量在栈中只存一个“地址”——就像身份证号,靠它才能找到堆里那个真正的对象。
看赋值时是否互相影响
这是最实用的现场检验法:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 基本类型赋值是“复制一份新值”:
let x = 100; let y = x; y = 200;→x还是100,互不干扰。 - 引用类型赋值是“复制一个地址”:
let obj1 = {a: 1}; let obj2 = obj1; obj2.a = 99;→obj1.a也变成99,因为它们指向同一块堆内存。
看能否被直接修改
基本类型是不可变的:字符串调用 .toUpperCase()、数字调用 .toFixed(),都不是改原值,而是返回一个新值。原变量内容始终没变。
引用类型是可变的:对象可以随时增删属性,数组可以 .push()、.pop(),这些操作直接修改堆内存中的原始数据。
顺便注意:虽然 const obj = {} 声明后不能重新赋值,但 obj.name = "张三" 完全合法——因为改的是堆里的内容,不是栈里的地址。
补充:类型检测的小技巧
用 typeof 能准确识别所有基本类型(typeof null 是历史 bug,返回 "object",需单独判断);
但对引用类型,typeof []、typeof {}、typeof /reg/ 都返回 "object",不够精细。
更可靠的方式是结合 Object.prototype.toString.call():
Object.prototype.toString.call([]) // "[object Array]"<br>Object.prototype.toString.call({}) // "[object Object]"<br>Object.prototype.toString.call(null) // "[object Null]"<br>Object.prototype.toString.call(123) // "[object Number]"

















