js的数据类型有几类?一共有几种?

JavaScript 作为一门弱类型语言,数据类型是其最基础也最易混淆的核心概念。很多开发者在实际开发中,常会因 "分不清数据类型""判断方法用错" 导致隐蔽的 bug------ 比如把null当成对象、用typeof判断数组返回object等。

本文将从官方定义、类型细分、判断方法三个维度,系统性拆解 JS 数据类型的核心知识:明确数据类型的分类与数量,对比不同判断方法的优劣,结合实战场景给出最优选型,帮你彻底摆脱数据类型判断的困扰。

一、先厘清核心概念:JS 数据类型的官方定义

在 ECMAScript 规范中,数据类型的分类有明确的版本演进:

  • ES5 及之前:分为「基本类型」和「引用类型」两大类;
  • ES6 及之后 :规范中正式定义为「原始类型(Primitive Type)」和「对象类型(Object Type)」,并新增Symbol类型,ES11 又新增BigInt类型。

核心原则:原始类型存储的是值,对象类型存储的是引用(内存地址),这是两类类型的本质区别,也是判断方法的核心依据。

二、JS 数据类型的完整清单:数量与细分

2.1 总数量:8 种(7 种原始类型 + 1 种对象类型)

截至 ECMAScript 2020(ES11),JS 共有 8 种数据类型,具体分类如下:

类型大类 具体类型 核心特征 示例
原始类型(7 种) String 字符串,不可变 "hello"'world'
Number 数值(包含整数、浮点数、NaN、Infinity) 1003.14NaN
Boolean 布尔值,仅true/false truefalse
Undefined 未定义,变量声明未赋值时的默认值 let a; // a的值为undefined
Null 空值,代表 "空对象指针" let b = null;
Symbol ES6 新增,唯一且不可变的原始值 Symbol('id')
BigInt ES11 新增,用于表示超大整数 9007199254740993n
对象类型(1 种) Object 复杂数据类型,包含子类型 普通对象{}、数组[]、函数function() {}、日期new Date()、正则/abc/

2.2 关键细节补充(避坑重点)

  1. null的特殊地位 :虽然typeof null返回object(JS 历史设计缺陷),但规范明确null属于原始类型,它的本质是 "表示空的对象引用",而非对象。

  2. NaN的特殊性NaN属于Number类型,且NaN !== NaN(唯一不等于自身的值),判断是否为NaN需用Number.isNaN()

  3. 对象类型的子类型 :数组、函数、日期、正则等本质都是Object的子类型,它们是 "特殊的对象":

    • 数组:Array.prototype.__proto__ === Object.prototype
    • 函数:Function.prototype.__proto__ === Object.prototype

三、JS 数据类型的判断方法:6 种方法对比(附场景选型)

判断数据类型是开发中的高频需求,不同方法有不同的适用场景,我们从 "精准度、易用性、适用范围" 三个维度拆解 6 种核心方法。

3.1 方法 1:typeof------ 最基础,适合判断原始类型(除 null)

核心原理

typeof 操作符返回一个字符串,表示操作数的类型,底层基于值的 "类型标签" 判断。

使用示例

javascript

运行

复制代码
typeof "abc"; // "string"
typeof 123; // "number"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object"(历史bug,重点避坑)
typeof Symbol('id'); // "symbol"
typeof 123n; // "bigint"
typeof {}; // "object"
typeof []; // "object"(无法区分数组和普通对象)
typeof function() {}; // "function"(唯一能精准判断的对象子类型)
优缺点 & 适用场景

✅ 优点:语法简单,性能高,能快速判断除 null 外的原始类型 、函数;❌ 缺点:无法区分null、普通对象、数组、日期等对象类型;🎯 适用场景:仅需快速判断原始类型(String/Number/Boolean/Undefined/Symbol/BigInt)或函数。

3.2 方法 2:instanceof------ 适合判断对象子类型(基于原型链)

核心原理

instanceof 检测构造函数的prototype是否出现在目标对象的原型链上,仅适用于对象类型。

使用示例

javascript

运行

复制代码
// 判断数组
[] instanceof Array; // true
[] instanceof Object; // true(数组原型链指向Object)

// 判断普通对象
({}) instanceof Object; // true

// 判断函数
(function(){}) instanceof Function; // true

// 判断日期
new Date() instanceof Date; // true

// 原始类型判断(全部返回false)
"abc" instanceof String; // false
123 instanceof Number; // false
优缺点 & 适用场景

✅ 优点:能精准区分对象子类型(数组、日期、正则等);❌ 缺点:无法判断原始类型、存在原型链污染风险(如修改Array.prototype)、跨 iframe 时判断失效;🎯 适用场景:判断自定义对象实例、内置对象子类型(数组 / 日期 / 正则)。

3.3 方法 3:Object.prototype.toString.call ()------ 最精准,万能判断法

核心原理

调用 Object 原型上的toString方法,返回格式为[object 类型名]的字符串,能精准识别所有类型(规范定义的 "终极判断法")。

使用示例

javascript

运行

复制代码
// 原始类型判断
Object.prototype.toString.call("abc"); // "[object String]"
Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"(精准识别null)
Object.prototype.toString.call(Symbol('id')); // "[object Symbol]"
Object.prototype.toString.call(123n); // "[object BigInt]"

// 对象类型判断
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(function(){}); // "[object Function]"
Object.prototype.toString.call(new Date()); // "[object Date]"
Object.prototype.toString.call(/abc/); // "[object RegExp]"
Object.prototype.toString.call(NaN); // "[object Number]"
封装实用工具函数(开箱即用)

javascript

运行

复制代码
/**
 * 精准判断数据类型
 * @param {any} value 要判断的值
 * @returns {string} 小写的类型名(如string、array、null等)
 */
function getType(value) {
  const typeStr = Object.prototype.toString.call(value);
  // 正则提取类型名并转小写
  return typeStr.slice(8, -1).toLowerCase();
}

// 测试
getType("abc"); // "string"
getType(null); // "null"
getType([]); // "array"
getType(new Date()); // "date"
getType(NaN); // "number"
优缺点 & 适用场景

✅ 优点:精准识别所有 8 种数据类型,包括null、数组、日期等;❌ 缺点:语法稍繁琐(建议封装成工具函数);🎯 适用场景:需要精准判断所有类型的场景(如通用工具库、表单校验)。

3.4 方法 4:Array.isArray ()------ 专门判断数组

核心原理

ES5 新增的数组专用判断方法,解决typeof无法判断数组的问题,是判断数组的最优解。

使用示例

javascript

运行

复制代码
Array.isArray([]); // true
Array.isArray({}); // false
Array.isArray(null); // false
Array.isArray(new Array()); // true
优缺点 & 适用场景

✅ 优点:简洁、精准、性能高;❌ 缺点:仅适用于数组判断;🎯 适用场景:专门判断是否为数组(推荐优先使用)。

3.5 方法 5:Number.isNaN ()------ 精准判断 NaN

核心原理

ES6 新增,区别于全局isNaN()(会先将参数转为数字),Number.isNaN()仅当参数是NaN且类型为 Number 时返回 true。

使用示例

javascript

运行

复制代码
// Number.isNaN(精准)
Number.isNaN(NaN); // true
Number.isNaN(123); // false
Number.isNaN("abc"); // false(全局isNaN返回true)

// 全局isNaN(不精准)
isNaN(NaN); // true
isNaN("abc"); // true("abc"转数字为NaN)
适用场景:精准判断是否为真正的 NaN。

3.6 方法 6:===(严格相等)------ 判断 undefined/null

核心原理

严格相等运算符(===)既判断值,也判断类型,是判断undefinednull的最优解。

使用示例

javascript

运行

复制代码
// 判断undefined
let a;
a === undefined; // true

// 判断null
let b = null;
b === null; // true

// 区分undefined和null
undefined === null; // false
适用场景:快速判断变量是否为undefinednull

3.7 所有判断方法对比表

判断方法 适用类型 精准度 核心优势 核心缺陷
typeof 原始类型(除 null)、函数 简单、高效 无法区分 null / 数组 / 普通对象
instanceof 对象子类型 能区分对象子类型 无法判断原始类型、原型链污染
Object.prototype.toString.call() 所有类型 万能、精准 语法稍繁琐
Array.isArray() 数组 简洁、精准 仅适用于数组
Number.isNaN() NaN 精准判断 NaN 仅适用于 NaN
=== undefined/null 简单、无歧义 仅适用于 undefined/null

四、实战场景选型指南:用对方法少踩坑

  1. 快速判断字符串 / 数字 / 布尔等原始类型 → 用typeof
  2. 判断数组 → 优先用Array.isArray()(简洁精准);
  3. 判断 undefined/null → 用===(如value === undefined);
  4. 判断 NaN → 用Number.isNaN()
  5. 判断自定义类实例 → 用instanceof(如new Person() instanceof Person);
  6. 通用场景(需精准判断所有类型) → 封装getType工具函数(基于Object.prototype.toString.call());
  7. 框架 / 工具库开发(极致精准) → 用Object.prototype.toString.call()

典型避坑案例

javascript

运行

复制代码
// 错误示例1:用typeof判断数组
if (typeof [] === 'array') { // 永远为false,typeof []返回object
  // 逻辑不会执行
}

// 正确示例1:判断数组
if (Array.isArray([])) {
  // 正确执行
}

// 错误示例2:用全局isNaN判断非数字
if (isNaN("abc")) { // 返回true,但"abc"不是NaN
  // 错误逻辑
}

// 正确示例2:判断NaN
if (Number.isNaN(value) && typeof value === 'number') {
  // 正确逻辑
}

// 错误示例3:判断null
if (typeof null === 'null') { // 返回false,typeof null返回object
  // 逻辑不会执行
}

// 正确示例3:判断null
if (value === null) {
  // 正确执行
}

五、总结:数据类型判断的核心原则

  1. 明确目标类型:先确定要判断的是原始类型还是对象类型,再选方法;
  2. 优先专用方法 :判断数组用Array.isArray()、判断 NaN 用Number.isNaN(),专用方法比通用方法更简洁;
  3. 通用场景选精准方法 :封装getType工具函数,一次封装终身复用;
  4. 避开历史坑 :牢记typeof null === 'object'是设计缺陷,判断 null 必须用===

数据类型判断看似简单,却是 JS 基础能力的试金石。掌握不同方法的适用场景,能让你在开发中避开 80% 的类型相关 bug,写出更健壮、更易维护的代码。

相关推荐
我是伪码农1 小时前
放大镜效果
javascript
被星1砸昏头1 小时前
C++中的状态模式实战
开发语言·c++·算法
Remember_9931 小时前
【数据结构】深入理解排序算法:从基础原理到高级应用
java·开发语言·数据结构·算法·spring·leetcode·排序算法
wanzhong23331 小时前
开发日记13-响应式变量
开发语言·前端·javascript·vue
郝学胜-神的一滴2 小时前
机器学习数据预处理:深入理解标准化与sklearn的StandardScaler
开发语言·人工智能·python·程序人生·机器学习·sklearn
踢球的打工仔2 小时前
typescript-类的静态属性和静态方法
前端·javascript·typescript
C_心欲无痕2 小时前
Next.js Script 组件详解
开发语言·javascript·ecmascript·next.js
匠心网络科技2 小时前
前端框架-Vue双向绑定核心机制全解析
前端·javascript·vue.js·前端框架
爱编码的傅同学2 小时前
【线程的同步与互斥】初识互斥量与锁
android·java·开发语言