JS类型检测大全:从零基础到高级应用

文章目录

    • [1. typeof 操作符](#1. typeof 操作符)
      • [typeof null 为什么是 object](#typeof null 为什么是 object)
    • [2. `instanceof` 操作符](#2. instanceof 操作符)
    • [3. `Object.prototype.toString.call()`(最准确的)](#3. Object.prototype.toString.call()(最准确的))
    • [4. Array.isArray()](#4. Array.isArray())
    • [5. `constructor` 属性](#5. constructor 属性)
    • 总结

在JavaScript中,有多种方法可以用来检测数据类型。每种方法都有其特定的用途和局限性。下面是几种常用的类型检测方法及其特点:

1. typeof 操作符

typeof 可以用来检测基本数据类型(除了nullundefined之间的区分)。

  • 优点:简单易用。
  • 缺点:无法准确区分 null数组,对象,都会返回 "object"。其他判断都正确
js 复制代码
console.log(typeof ½); // "number"
console.log(typeof 'str'); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" 
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"

typeof null 为什么是 object

在最初的 JS 实现中,typeof 操作符的设计目的是返回一个字符串,指示未经计算的操作数的类型。然而,在处理null时,由于null最初被设计为表示"无对象",因此将其类型视为 "object"。这个决定导致了typeof null返回 "object"

解决办法

  1. 使用严格相等运算符(===
js 复制代码
if (value === null) {
  console.log("这是一个 null");
}
  1. 使用 Object.prototype.toString.call()
    这是最准确的方法,可以明确地区分 null 与其他类型。
js 复制代码
if (Object.prototype.toString.call(value) === "[object Null]") {
  console.log("这是一个 null");
}
  1. 自定义类型检查
    写一个函数用来检测
js 复制代码
function getType(value) {
  if (value === null) {
    return "null";
  }
  return typeof value;
}

console.log(getType(null)); // "null"
console.log(getType(42)); // "number"
console.log(getType("hello")); // "string"

2. instanceof 操作符

instanceof 用来检查一个对象在其原型链中是否存在一个构造函数的prototype属性

  • 优点:可以用来区分不同的引用类型。
  • 缺点:不能用来检测基础类型。跨iframe使用时可能会出现问题。
js 复制代码
console.log([] instanceof Array); // true
console.log({} instanceof Object); // true
console.log(function(){} instanceof Function); // true

3. Object.prototype.toString.call()(最准确的)

这是最可靠的一种类型检测方法,可以准确地区分所有类型,包括基础类型和引用类型。

使用Object对象的原型方法toString方法来判断

优点:非常准确,支持所有类型。

缺点:语法稍微复杂一点。

  • 基本类型
js 复制代码
console.log(Object.prototype.toString.call(1)); // "[object Number]"
console.log(Object.prototype.toString.call('str')); // "[object String]"
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(BigInt(123456789012345678901234567890n))); // "[object BigInt]"
  • 引用类型
js 复制代码
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("abc"))); // "[object RegExp]"
console.log(Object.prototype.toString.call(new Map())); // "[object Map]"
console.log(Object.prototype.toString.call(new Set())); // "[object Set]"
console.log(Object.prototype.toString.call(new WeakMap())); // "[object WeakMap]"
console.log(Object.prototype.toString.call(new WeakSet())); // "[object WeakSet]"
console.log(Object.prototype.toString.call(new Error())); // "[object Error]"
  • 特殊对象
js 复制代码
console.log(Object.prototype.toString.call(Math)); // "[object Math]"
console.log(Object.prototype.toString.call(JSON)); // "[object JSON]"
console.log(Object.prototype.toString.call(Promise.resolve())); // "[object Promise]"
  • 自定义检测方法 -便捷使用
js 复制代码
function getType(value) {
  return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}

console.log(getType(42)); // "number"
console.log(getType("Hello, World!")); // "string"
console.log(getType(true)); // "boolean"
console.log(getType(undefined)); // "undefined"
console.log(getType(null)); // "null"
console.log(getType(Symbol("symbol"))); // "symbol"
console.log(getType({})); // "object"
console.log(getType([])); // "array"
console.log(getType(function() {})); // "function"
console.log(getType(new Date())); // "date"
console.log(getType(new RegExp("abc"))); // "regexp"
console.log(getType(new Map())); // "map"
console.log(getType(Promise.resolve())); // "promise"

4. Array.isArray()

专门用于检测是否为数组。

优点:简单明了,专用于数组检测。

缺点:只能用于数组。

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

5. constructor 属性

通过检查对象的constructor属性来确定其构造函数。

优点:可以用于大多数引用类型。

缺点:constructor 对象访问它的构造函数,如果创建一个对象改变它的原型,则可能不准确。对于基础类型无效。

js 复制代码
console.log((2).constructor == Number); //true
console.log((true).constructor == Boolean); //true
console.log(("string").constructor == String); //true

console.log(([]).constructor === Array); // true
console.log(({}).constructor === Object); // true
console.log((function(){}).constructor === Function); // true

// 改变原型之后
function Fn(){}

Fn.prototype  = new Array();
var f= new Fn();

console.log(f.constructor === Fn);//false
console.log(f.constructor === Array);//true

总结

  • 对于基础类型,推荐使用 typeof 或 Object.prototype.toString.call()。
  • 对于引用类型,尤其是需要区分具体类型时,Object.prototype.toString.call() 是最佳选择。
  • 如果只需要判断是否为数组,Array.isArray() 是最直接的方法。
  • instanceof 在某些情况下也很有用,特别是当你需要检查对象是否是由特定构造函数创建的时候。
相关推荐
小村儿13 小时前
连载10-Sub-agents 深度解析:从源码理解 Claude Code 的分身术
前端·后端·ai编程
笨拙的老猴子13 小时前
[特殊字符] Java GC机制详解:G1、ZGC、Shenandoah全面解析与版本演进对比
java·开发语言
水木流年追梦13 小时前
大模型入门-Reward 奖励模型训练
开发语言·python·算法·leetcode·正则表达式
电子云与长程纠缠13 小时前
UE5制作六边形包裹球体效果
开发语言·python·ue5
IT_陈寒13 小时前
Vite动态导入把我坑惨了,原来要这样用才对
前端·人工智能·后端
砍材农夫13 小时前
物联网 基于netty构建mqtt协议规范(遗嘱与保留消息)
java·开发语言·物联网·netty
DFT计算杂谈13 小时前
KPROJ编译教程
java·前端·python·算法·conda
觅_13 小时前
前端学习后端的时候 选择一个技术
前端·学习
独泪了无痕13 小时前
CryptoJS:数据安全的JavaScript加密利器
前端·vue.js·node.js
froginwe1114 小时前
Python3 迭代器与生成器
开发语言