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 在某些情况下也很有用,特别是当你需要检查对象是否是由特定构造函数创建的时候。
相关推荐
장숙혜3 分钟前
JavaScript正则表达式解析:模式、方法与实战案例
开发语言·javascript·正则表达式
安大小万20 分钟前
C++ 学习:深入理解 Linux 系统中的冯诺依曼架构
linux·开发语言·c++
随心Coding24 分钟前
【零基础入门Go语言】错误处理:如何更优雅地处理程序异常和错误
开发语言·后端·golang
T.Ree.28 分钟前
C语言_自定义类型(结构体,枚举,联合)
c语言·开发语言
Channing Lewis30 分钟前
python生成随机字符串
服务器·开发语言·python
小熊科研路(同名GZH)1 小时前
【Matlab高端绘图SCI绘图模板】第002期 绘制面积图
开发语言·matlab
鱼是一只鱼啊1 小时前
.netframeworke4.6.2升级.net8问题处理
开发语言·.net·.net8
Channing Lewis1 小时前
如何实现网页不用刷新也能更新
前端