JavaScript 数据类型详解:分类、判断方式与核心差异
JavaScript 数据类型分为基础类型和引用类型,共 8 种。常用判断方法包括 typeof、instanceof、Object.prototype.toString.call() 及特殊方法。两类类型在存储位置(栈/堆)、赋值传参机制(值传递/引用传递)、可变性、比较方式及内存管理上存在核心差异。掌握这些知识有助于编写健壮代码并避免隐蔽 Bug。

JavaScript 数据类型分为基础类型和引用类型,共 8 种。常用判断方法包括 typeof、instanceof、Object.prototype.toString.call() 及特殊方法。两类类型在存储位置(栈/堆)、赋值传参机制(值传递/引用传递)、可变性、比较方式及内存管理上存在核心差异。掌握这些知识有助于编写健壮代码并避免隐蔽 Bug。

在 JavaScript 编程中,数据类型是构建所有程序的基础,理解它的分类、判断方式以及不同类型的核心差异,是写出健壮代码、避免隐蔽 Bug 的关键。本文将全面拆解 JS 数据类型的相关知识点,从分类到实操,帮你彻底吃透这一基础核心内容。
JavaScript 数据类型分为两大类别,共计8 种具体类型,这一划分是基于数据的存储方式、访问机制的本质差异而来。
基础数据类型是不可再分的最小数据单元,直接存储具体的值,具体包括:
String:字符串类型,用于表示文本数据,如 "Hello JS"、'123'(单引号、双引号、反引号均可包裹);Number:数值类型,包含整数、浮点数以及特殊数值,如 100、3.14、NaN(非数字)、Infinity(无穷大);Boolean:布尔类型,仅包含两个值,用于表示真假状态:true(真)和 false(假);Undefined:未定义类型,只有一个值 undefined,表示变量已声明但未赋值,或访问不存在的对象属性时的返回值;Null:空值类型,只有一个值 null,表示一个有意指向的'空对象',通常用于手动清空变量的引用;Symbol:ES6 新增的唯一标识类型,每个 Symbol 实例都是独一无二的,用于解决对象属性名冲突问题,如 Symbol('name');BigInt:ES10 新增的大整数类型,用于表示超出 Number 类型安全范围(±2^53-1)的整数,后缀以 n 标识,如 9007199254740993n。引用数据类型本质是对数据的引用,存储的是内存地址,而非具体值,核心类型为 Object,常见的衍生 / 内置类型都属于 Object 的子类:
{ name: "张三", age: 20 };[1, 2, 3, "JS"](本质是有序索引的对象);function fn() { return 1; }(本质是可执行的对象);/^\d+$/;new Date() 等。在开发中,我们经常需要判断变量的数据类型,不同方法有各自的适用场景和局限性,以下是 4 种核心判断方式:
typeof 是最常用的基础判断方法,返回一个表示数据类型的字符串,语法:typeof 变量/值。
// 基础数据类型判断(除 null 外均准确)
console.log(typeof "abc"); // "string"
console.log(typeof 123); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof Symbol("id")); // "symbol"
console.log(typeof 123n); // "bigint"
// 引用数据类型判断(局限性:均返回 "object" 或 "function")
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof /abc/); // "object"
console.log(typeof function(){}); // "function"(唯一能准确区分的引用类型)
// 经典坑:null 会返回 "object"
console.log(typeof null); // "object"
null 和普通对象,对 null 会误判为 "object";"object"。instanceof 基于原型链判断,用于检测一个对象是否是某个构造函数的实例,语法:变量 instanceof 构造函数。
// 区分不同引用类型
const arr = [1, 2, 3];
const obj = { name: "张三" };
const fn = function() {};
const reg = /^\d+$/;
const date = new Date();
console.log(arr instanceof Array); // true
console.log(obj instanceof Object); // true
console.log(fn instanceof Function); // true
console.log(reg instanceof RegExp); // true
console.log(date instanceof Date); // true
// 基础数据类型返回 false(除了通过构造函数创建的包装对象)
console.log(123 instanceof Number); // false
console.log(new Number(123) instanceof Number); // true
这是最准确、最通用的判断方式,通过调用 Object 原型上的 toString 方法,返回格式为 "[object 类型名]" 的字符串,能精准区分所有数据类型。
// 基础数据类型全准确
console.log(Object.prototype.toString.call("abc")); // "[object String]"
console.log(Object.prototype.toString.call(123)); // "[object Number]"
console.log(Object.prototype.toString.call(true)); // "[object Boolean]"
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call(Symbol("id"))); // "[object Symbol]"
console.(...());
.(...([]));
.(...({}));
.(...((){}) );
.(...());
.(...( ()));
call() 改变 this 指向,直接调用 toString() 会根据对象自身的方法返回结果(如数组调用 toString() 会返回数组元素拼接字符串)。除了上述通用方法,还有一些针对性的判断方式:
Array.isArray():专门判断数组,比 instanceof 更可靠(可跨窗口判断),如 Array.isArray([1,2,3]) // true;Number.isNaN():专门判断是否为真正的 NaN(弥补 typeof NaN 返回 "number" 的缺陷),如 Number.isNaN(NaN) // true,Number.isNaN("123") // false。基础数据类型和引用数据类型的差异,本质源于存储位置、访问方式的不同,具体体现在以下 5 个核心方面:
引用数据类型:采用引用传递,赋值或传参时,复制的是栈内存中的引用地址,新旧变量 / 函数参数指向堆内存中的同一个数据,修改其中一个会影响所有指向该地址的变量;
let obj1 = { name: "张三" };
let obj2 = obj1; // 复制引用地址,obj1 和 obj2 指向同一个堆内存对象
obj2.name = "李四";
console.log(obj1.name); // "李四"(obj1 受 obj2 修改影响)
基础数据类型:采用值传递,赋值或传参时,会创建一份值的副本,新旧变量 / 函数参数与原变量互不影响,修改其中一个不会改变另一个;
let a = 10;
let b = a; // 复制 a 的值,b 是独立副本
b = 20;
console.log(a); // 10(a 不受 b 修改影响)
引用数据类型:可变(Mutable),我们可以直接修改堆内存中的数据内容(如添加 / 删除对象属性、修改数组元素),无需创建新的对象;
let arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [1,2,3,4](原数组被直接修改)
基础数据类型:不可变(Immutable),基础类型的值一旦创建就无法修改,我们平时对字符串、数字的'修改',本质是创建了一个新的值,而非修改原有的值;
let str = "hello";
str.toUpperCase(); // "HELLO"
console.log(str); // "hello"(原字符串未被修改,返回了新字符串)
引用数据类型:引用地址比较,判断两个引用类型变量是否相等,比较的是它们是否指向堆内存中的同一个地址,而非数据内容是否一致;
let obj1 = { name: "张三" };
let obj2 = { name: "张三" };
console.log(obj1 === obj2); // false(两个对象在堆内存中是不同的地址,内容相同但引用不同)
基础数据类型:值比较,判断两个基础类型变量是否相等,只需比较它们的具体值是否一致(== 会进行类型转换,=== 严格比较值和类型);
console.log(10 === 10); // true
console.log("hello" === "hello"); // true
console.log(10 === "10"); // false(类型不同)
掌握这些知识点,能帮助我们在开发中更合理地使用变量、避免数据修改冲突、精准判断数据类型,为编写高效、可靠的 JavaScript 代码打下坚实基础。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online