当前位置:首页 > 文章列表 > 文章 > 前端 > JS判断数据类型的方法有哪些?

JS判断数据类型的方法有哪些?

2025-08-03 11:25:30 0浏览 收藏

哈喽!今天心血来潮给大家带来了《JS如何判断数据类型?》,想必大家应该对文章都不陌生吧,那么阅读本文就都不会很困难,以下内容主要涉及到,若是你正在学习文章,千万别错过这篇文章~希望能帮助到你!

判断JavaScript数据类型需根据场景选择方法:1. typeof适用于基本类型判断,但对null和对象均返回'object',存在局限;2. instanceof通过原型链检测对象类型,适合判断自定义类或内置对象如Array、Date,但在跨全局环境时不可靠;3. Object.prototype.toString.call()最精确,能区分所有内置类型,推荐用于需要高准确性的场景;4. constructor属性易被修改,不推荐依赖。typeof null返回'object'是因早期实现中null的位模式与对象标签冲突,属历史遗留问题。判断数组应优先使用Array.isArray(),因其不依赖构造函数实例,可避免跨环境失效。判断纯对象推荐使用Object.prototype.toString.call(value) === '[object Object]',该方法能准确排除数组、函数等非普通对象,且兼容性强,是目前最可靠的方案。

js中如何判断数据类型

在JavaScript里,判断数据类型这事儿,说简单也简单,说复杂也挺复杂。简单在于我们有几个内置的工具,复杂在于它们各自都有点“脾气”或者说“陷阱”,用不对地方就可能踩坑。核心来说,我们通常会用到typeofinstanceofObject.prototype.toString.call(),以及偶尔会考虑constructor属性。每种方法都有它的适用场景和局限性,理解这些,才能在实际开发中游刃有余。

js中如何判断数据类型

解决方案

判断JavaScript数据类型,并没有一个“万能药”,而是需要根据具体场景和你想判断的“类型”深度来选择合适的方法。

  1. typeof 操作符: 这是最直观也最常用的一个。它能很好地识别基本数据类型:'string''number''boolean''symbol''bigint''undefined'。对于函数,它会返回'function',这算是它一个比较特殊的待遇,毕竟函数在JS里也是一种特殊的对象。然而,它的一个大坑是,对于所有非函数对象(包括数组、null),它统一返回'object'。所以,如果你想区分数组和普通对象,或者判断一个值是不是nulltypeof就显得力不从心了。

    js中如何判断数据类型
    console.log(typeof "hello");      // "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 10n);          // "bigint"
    console.log(typeof {});           // "object"
    console.log(typeof []);           // "object"
    console.log(typeof null);         // "object"  —— 经典的坑
    console.log(typeof function(){}); // "function"
  2. instanceof 操作符: 这个操作符主要用来检测构造函数的prototype属性是否出现在某个实例对象的原型链上。它非常适合用来判断一个对象是不是某个特定类的实例,比如判断一个变量是不是ArrayDateRegExp等内置构造函数的实例,或者你自己定义的类的实例。但它也有局限性,它不能用于判断基本数据类型,而且在多全局环境(比如iframe之间)判断对象时可能会失效,因为每个iframe都有自己的全局对象和构造函数。

    let arr = [1, 2, 3];
    let obj = {};
    let date = new Date();
    
    console.log(arr instanceof Array);    // true
    console.log(obj instanceof Object);   // true
    console.log(date instanceof Date);    // true
    console.log(arr instanceof Object);   // true (因为数组也是对象)
    console.log("hello" instanceof String); // false (基本类型不是String对象的实例)
  3. Object.prototype.toString.call() 方法: 这绝对是判断数据类型最“靠谱”的方法之一,尤其是在需要精确区分内置对象类型时。Object.prototype.toString方法在执行时,会返回一个表示该对象类型的字符串,格式通常是"[object Type]",其中Type是对象的内部[[Class]]属性值。通过call方法,我们可以强制让任何值调用这个toString方法,从而得到其准确的内部类型描述。

    js中如何判断数据类型
    console.log(Object.prototype.toString.call("hello"));      // "[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({}));           // "[object Object]"
    console.log(Object.prototype.toString.call([]));           // "[object Array]"
    console.log(Object.prototype.toString.call(function(){})); // "[object Function]"
    console.log(Object.prototype.toString.call(new Date()));   // "[object Date]"
    console.log(Object.prototype.toString.call(new RegExp())); // "[object RegExp]"
    console.log(Object.prototype.toString.call(Symbol('id'))); // "[object Symbol]"
    console.log(Object.prototype.toString.call(10n));          // "[object BigInt]"

    这是我个人最推荐的方法,因为它几乎能覆盖所有内置类型,并且结果非常精确。

  4. constructor 属性: 每个对象都有一个constructor属性,指向创建该实例的构造函数。你可以通过它来判断类型。

    let arr = [1, 2];
    let obj = {};
    console.log(arr.constructor === Array);  // true
    console.log(obj.constructor === Object); // true

    然而,这个方法并不是特别可靠。constructor属性是可以被修改的,或者在原型链上被覆盖,这会影响判断结果。比如,一个自定义类继承了Array,它的constructor可能指向它自己的类,而不是Array。所以,除非你对代码的控制力非常强,否则不建议过度依赖它。

为什么typeof null会返回'object'?这算是一个设计缺陷吗?

这确实是JavaScript里一个长久以来的“梗”,typeof null 返回 'object'。从现代编程语言的设计角度看,这无疑是一个不一致的地方,甚至可以说是一个“历史遗留问题”或者“设计缺陷”。但要说它是缺陷,不如说它是一个“意外”。

这个行为的根源在于JavaScript的早期实现。在JavaScript的第一个版本中,值是以32位字来存储的。其中,低位(或某些位)被用来表示值的类型标签。

  • 对象的类型标签是 000
  • null 被表示为机器码的 0。 所以,当typeof操作符检查null时,它看到的是000这个类型标签(因为0的二进制表示就是全零),因此错误地判断它为'object'

这确实不是一个有意的设计,而是一个实现上的巧合。修复它会破坏大量的现有代码,因为很多老旧的JavaScript代码可能已经依赖了这个行为(虽然这听起来有点不可思议,但确实如此)。因此,为了保持向后兼容性,这个“bug”或者说“怪癖”就被保留了下来。

在实际开发中,我们通常会先判断一个值是否为null,再进行typeof判断,以避免这个误区:

function checkType(value) {
    if (value === null) {
        return "null";
    }
    return typeof value;
}

console.log(checkType(null)); // "null"
console.log(checkType({}));   // "object"

判断数组类型时,为什么Array.isArray()比instanceof更可靠?

在判断一个变量是否是数组时,Array.isArray()无疑是黄金标准,它比instanceof Array更可靠。这背后的原因主要在于JavaScript的“领域”概念,或者更通俗地说,是“跨iframe”或“跨全局环境”的问题。

想象一下,你在一个网页里嵌入了一个iframe。这个iframe内部有自己的JavaScript运行环境,它有自己的全局对象、自己的Array构造函数。 如果你在父页面创建了一个数组parentArray = [],然后把它传递给iframe。在iframe内部,如果你尝试parentArray instanceof Array,结果可能会是false。这是因为parentArray是由父页面的Array构造函数创建的,而iframe内部的Array构造函数是它自己环境里的,两者虽然名字相同,但它们在内存中是不同的对象。instanceof的原理是检查对象的原型链是否包含构造函数的prototype属性,但在这种跨域(这里指不同的JavaScript全局上下文)的情况下,它们的prototype对象并不是同一个。

Array.isArray()则不同,它不依赖于具体的构造函数实例。它在底层会检查对象的内部[[Class]]属性(在ES6之后,这个概念被Symbol.toStringTag取代,但原理类似),或者其他更底层的、与特定全局环境无关的机制来判断。简单来说,它会直接问“你是不是一个真正的数组?”而不是“你是通过我这个Array构造函数创建的吗?”

// 假设这是在浏览器环境中,通过iframe模拟跨全局环境
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const iframeWin = iframe.contentWindow;

// 在iframe中创建的数组
const iframeArray = iframeWin.Array(1, 2, 3);

// 在主页面中判断
console.log(iframeArray instanceof Array);    // 可能会是 false (取决于浏览器实现和沙箱策略)
console.log(Array.isArray(iframeArray));      // true (始终可靠)

// 清理
document.body.removeChild(iframe);

因此,为了确保代码在各种复杂环境下(尤其是在涉及多窗口、iframe、Web Workers等场景)的健壮性,始终推荐使用Array.isArray()来判断数组。

如何判断一个变量是纯粹的JavaScript对象(即{}或new Object()创建的)?

要判断一个变量是否是“纯粹”的JavaScript对象,也就是那些通过对象字面量{}new Object()创建的,而不是数组、函数、日期、正则表达式等特定类型的对象,这是一个常见的需求。typeof在这里会返回'object',但它并不能区分这些具体类型。

最可靠且我个人常用的方法,依然是借助Object.prototype.toString.call()

function isPlainObject(value) {
    if (typeof value !== 'object' || value === null) {
        return false;
    }
    return Object.prototype.toString.call(value) === '[object Object]';
}

console.log(isPlainObject({}));               // true
console.log(isPlainObject(new Object()));     // true
console.log(isPlainObject([]));               // false ([object Array])
console.log(isPlainObject(new Date()));       // false ([object Date])
console.log(isPlainObject(function(){}));     // false ([object Function])
console.log(isPlainObject(null));             // false
console.log(isPlainObject(123));              // false

这个方法之所以可靠,是因为Object.prototype.toString在非普通对象上会返回其特有的[[Class]]字符串,而只有纯粹的Object实例才会返回[object Object]

除了这个,还有一些其他思路,但各有其局限性:

  1. 检查原型链: 可以检查对象的原型是否直接等于Object.prototype

    function isPureObjectByProto(value) {
        if (typeof value !== 'object' || value === null) {
            return false;
        }
        let proto = Object.getPrototypeOf(value);
        // 如果没有原型 (比如Object.create(null)),或者原型就是Object.prototype
        return proto === null || proto === Object.prototype;
    }
    
    console.log(isPureObjectByProto({}));               // true
    console.log(isPureObjectByProto(Object.create(null))); // true (无原型对象)
    console.log(isPureObjectByProto([]));               // false (原型是Array.prototype)

    这个方法也挺好,尤其能处理Object.create(null)创建的“纯粹”对象(它们没有原型链,因此Object.getPrototypeOf返回null)。但如果一个对象是通过继承某个自定义类而来的,即使它看起来像一个普通对象,Object.getPrototypeOf也不会是Object.prototype

  2. 结合constructor属性(不推荐): 虽然前面说了constructor不靠谱,但有时也会被用来尝试判断。

    function isPlainObjectByConstructor(value) {
        if (typeof value !== 'object' || value === null) {
            return false;
        }
        // 还要排除像Date, Array等内置对象
        return value.constructor === Object;
    }
    
    console.log(isPlainObjectByConstructor({})); // true
    console.log(isPlainObjectByConstructor([])); // false
    // 但如果constructor被修改,或者来自不同的iframe,就会出问题

    这个方法过于脆弱,因为constructor属性太容易被篡改或继承链影响。

综合来看,判断纯粹的JavaScript对象,Object.prototype.toString.call(value) === '[object Object]'依然是最稳健、最推荐的做法。它简洁明了,且在各种复杂场景下都能给出准确的判断。

好了,本文到此结束,带大家了解了《JS判断数据类型的方法有哪些?》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!

CSS混合模式详解:mix-blend-mode使用教程CSS混合模式详解:mix-blend-mode使用教程
上一篇
CSS混合模式详解:mix-blend-mode使用教程
HTMLmargin设置技巧与应用详解
下一篇
HTMLmargin设置技巧与应用详解
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    511次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    498次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 千音漫语:智能声音创作助手,AI配音、音视频翻译一站搞定!
    千音漫语
    千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
    100次使用
  • MiniWork:智能高效AI工具平台,一站式工作学习效率解决方案
    MiniWork
    MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
    92次使用
  • NoCode (nocode.cn):零代码构建应用、网站、管理系统,降低开发门槛
    NoCode
    NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
    111次使用
  • 达医智影:阿里巴巴达摩院医疗AI影像早筛平台,CT一扫多筛癌症急慢病
    达医智影
    达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
    103次使用
  • 智慧芽Eureka:更懂技术创新的AI Agent平台,助力研发效率飞跃
    智慧芽Eureka
    智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
    104次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码