还在被JavaScript数据类型搞糊涂?一篇文章帮你彻底搞懂!

掌握数据类型,写出更健壮可靠的代码

如果你是初学者,可能会对 nullundefined 的区别感到困惑;如果你已经有经验,或许曾在类型判断和引用赋值上踩过坑。不用担心,这篇文章将带你从入门到精通,彻底搞懂 JavaScript 数据类型的所有细节。

一、JavaScript 的两大数据类型家族

JavaScript 的数据类型主要分为两大类:基本数据类型 (原始类型)和引用数据类型(对象类型)。

截至 ES2023,JavaScript 共有 8 种数据类型。

基本数据类型包括:

  1. Undefined :表示变量已声明但未赋值,只有一个值 undefined
  2. Null :表示空值或不存在的对象,只有一个值 null
  3. Boolean :表示逻辑值,只有 truefalse 两个值
  4. Number :表示整数或浮点数,还包括特殊值 NaN(Not a Number)和 Infinity
  5. String:表示文本数据,可以用单引号、双引号或反引号包裹
  6. Symbol:ES6 新增,表示唯一的、不可变的值
  7. BigInt:ES2020 新增,表示任意精度的整数

引用数据类型 主要是 Object,还包括其派生类型:

  • Object:键值对的集合
  • Array:有序的元素集合
  • Function:可执行的对象
  • 其他内置对象:如 Date、RegExp、Map、Set 等

二、基本数据类型 vs 引用数据类型:核心区别

为什么要把数据类型分成这两大类呢?因为它们在使用上有根本性的区别。

存储位置不同 基本数据类型存储在栈内存 中,直接存储值本身。引用数据类型存储在堆内存中,变量在栈内存中存储的是指向堆内存的地址引用。

赋值方式不同 基本数据类型赋值是复制值,赋值后两个变量互不影响。

javascript 复制代码
let a = 10;
let b = a; // 值拷贝
b = 20;
console.log(a); // 10(互不影响)

引用数据类型赋值是复制引用,赋值后两个变量指向同一个对象。

javascript 复制代码
let obj1 = { name: 'John' };
let obj2 = obj1; // 指针拷贝
obj2.name = 'Alice';
console.log(obj1.name); // 'Alice'(指向同一对象)

比较方式不同 基本数据类型比较的是是否相等。

javascript 复制代码
5 === 5; // true

引用数据类型比较的是内存地址(是否同一个对象)。

javascript 复制代码
{} === {}; // false

是否可变 基本数据类型是不可变 的,修改时会创建新值。引用数据类型是可变的,可以直接修改对象属性。

三、typeof:类型判断的常用工具

typeof 操作符是最常用的类型判断工具,它可以返回一个字符串,表示变量的数据类型。

javascript 复制代码
console.log(typeof "Hello"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object"(注意:这是一个历史遗留问题)
console.log(typeof Symbol("id")); // "symbol"
console.log(typeof 123n); // "bigint"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function() {}); // "function"

需要注意的是,typeof null 返回 "object" 是 JavaScript 早期实现的一个历史遗留问题,而不是因为 null 本身是一个对象。

另外,typeof 对于数组也返回 "object",这显然不够精确。对于数组的类型判断,可以使用 Array.isArray() 方法。

javascript 复制代码
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false

四、null vs undefined:看似相似却不同

很多开发者对 nullundefined 的区别感到困惑。它们都表示某种"空"的概念,但在语义和使用上有所不同。

undefined 表示变量已声明但未赋值,是 JavaScript 引擎给变量分配的默认值。

javascript 复制代码
let x;
console.log(x); // 输出: undefined

null 表示"空"或"无值",是一个显式赋值的空对象指针,通常用于手动释放对象引用。

javascript 复制代码
let user = null; // 主动设置为空

在比较时,它们也表现出有趣的行为:

javascript 复制代码
console.log(null == undefined); // true(抽象相等比较)
console.log(null === undefined); // false(严格相等比较,类型不同)

五、特殊数据类型:Symbol 和 BigInt

Symbol 是 ES6 引入的一种新的原始数据类型,表示唯一的值。即使使用相同的描述创建两个 Symbol,它们也是不相等的。

javascript 复制代码
let s1 = Symbol('id');
let s2 = Symbol('id');
console.log(s1 === s2); // false

Symbol 常用于对象属性的键,确保属性名的唯一性,避免属性冲突。

javascript 复制代码
const ID = Symbol('id');
const user = {
  [ID]: 123,
  name: 'Alice'
};

BigInt 是 ES2020 引入的一种新的原始数据类型,用于表示任意精度的整数。JavaScript 的 Number 类型无法安全地表示大于 2^53 的整数,BigInt 解决了这个问题。

javascript 复制代码
const bigNum = 9007199254740991n; // 注意后面的 n
const alsoBig = BigInt("9007199254740991");

BigInt 不能直接与 Number 类型进行混合运算,需要先进行转换。

六、常见陷阱与最佳实践

陷阱一:意外修改共享对象由于引用类型的赋值是复制引用而不是值,可能会意外修改共享对象。

javascript 复制代码
let obj1 = { name: 'John' };
let obj2 = obj1; // 复制引用,而不是对象本身
obj2.name = 'Alice'; // 修改了 obj1 和 obj2 共享的对象
console.log(obj1.name); // 'Alice'

解决方案:需要时使用深拷贝创建新对象。

陷阱二:NaN 的特殊行为 NaN(Not a Number)是一个特殊的数字值,表示不是一个数字。它有一个独特的行为:它是 JavaScript 中唯一不等于自身的值。

javascript 复制代码
console.log(NaN === NaN); // false

解决方案:使用 isNaN() 函数或 Number.isNaN() 方法检查 NaN。

javascript 复制代码
console.log(isNaN(NaN)); // true
console.log(isNaN("abc")); // true(无法转换为数字)
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("abc")); // false(Number.isNaN 更严格)

最佳实践一:使用全等比较 尽量使用 === 而不是 == 进行比较,避免隐式类型转换带来的意外结果。

最佳实践二:明确的类型检查使用组合方式进行类型检查,提高代码的健壮性。

javascript 复制代码
// 检查数组
function isArray(obj) {
  return Array.isArray ? Array.isArray(obj) : Object.prototype.toString.call(obj) === "[object Array]";
}

// 检查 null
function isNull(obj) {
  return obj === null;
}

// 检查 undefined
function isUndefined(obj) {
  return obj === void 0; // 或者 typeof obj === "undefined"
}

七、总结

JavaScript 的数据类型看似简单,但深入理解它们对于编写健壮、可靠的代码至关重要。基本数据类型和引用数据类型在存储、赋值和比较上的根本差异,是许多常见编程错误的根源。

通过掌握 typeofinstanceofObject.prototype.toString.call() 等类型判断方法,以及理解 nullundefined 的区别,你可以避免许多常见的陷阱。

希望这篇文章帮助你彻底理解了 JavaScript 的数据类型。如果有任何问题或想法,欢迎在评论区留言讨论!

相关推荐
诗书画唱10 分钟前
JavaScript 基础核心知识点总结:从使用方式到核心语法
开发语言·javascript·ecmascript
水冗水孚1 小时前
通俗易懂地理解深度遍历DFS、和广度遍历BFS
javascript·算法
未来之窗软件服务1 小时前
网页提示UI操作-适应提示,警告,信息——仙盟创梦IDE
javascript·ide·ui·仙盟创梦ide·东方仙盟
爱学大树锯1 小时前
【Ruoyi 解密 - 09. 前端探秘2】------ 接口路径及联调实战指南
前端
老华带你飞1 小时前
校园二手书交易|基于SprinBoot+vue的校园二手书交易管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·小程序·毕设·校园二手书交易管理系统
萌程序.1 小时前
创建Vue项目
前端·javascript·vue.js
VT.馒头1 小时前
【力扣】2704. 相等还是不相等
前端·javascript·算法·leetcode·udp
linweidong2 小时前
Vue前端国际化完全教程(企业内部实践教程)
前端·javascript·vue.js·多语言·vue-i18n·动态翻译·vue面经
lukeLiouu2 小时前
augment不能白嫖了?试试claude code + GLM4.5,十分钟搞定起飞🚀
前端
点正2 小时前
使用 Volta 管理 Node 版本和 chsrc 换源:提升开发效率的完整指南
前端