JavaScript的中的类型判断和Object.prototype.toString()的底层原理

深入探讨JavaScript中的类型判断方法

JavaScript 是一种动态类型的编程语言,因此在处理不同类型的数据时,我们需要一些工具来准确地了解数据的类型。在这篇文章中,我们将深入探讨 JavaScript 中四种常用的数据类型判断方法:typeof、instanceof、Object.prototype.toString() 和 Array.isArray()。每种方法都有其独特的优势和适用场景,我们将逐一剖析它们的特点。

1. typeof:原始类型和函数的利器

JavaScript 中最常用的类型判断方法之一是 typeof 操作符。它能够快速而准确地判断除了 null 之外的所有原始类型 ,包括 undefined、boolean、number、string、symbol 以及最具灵活性的 function 类型。

js 复制代码
typeof 42; // 'number'
typeof 'hello'; // 'string'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof Symbol('symbol'); // 'symbol'
typeof function() {}; // 'function'

2. instanceof:引用类型的身份证

instanceof 是用于判断对象是否是特定构造函数的实例的操作符。与 typeof 不同,instanceof 主要用于引用类型,通过检查对象的原型链是否包含特定构造函数的 prototype 来判断。instanceof可以准确判断除了Object(对象)以外的引用类型。

js 复制代码
let obj = {}
let arr = [1,2,3]
let date = new Date()
let fn = function(){}

console.log(obj instanceof Object);// true
console.log(arr instanceof Object);// true
console.log(arr instanceof Array);// true
console.log(date instanceof Date);// true
console.log(fn instanceof Function);// true

3. Object.prototype.toString():通用的类型判断工具

Object.prototype.toString() 是一种通用的类型判断工具,它可以准确判断任何类型的值 ,包括原始类型和引用类型。通过调用 Object.prototype.toString.call(),我们能够获取一个描述类型的字符串,再通过slice方法切片就能够得到数据类型了。使用Object.prototype.toString.call().slice(8,-1)能够准确的以字符串形式得到任意一个元素的数据类型。

js 复制代码
let str = 'hello'
let num = 123
let obj = {}
let arr = [1,2]

console.log(Object.prototype.toString.call(str));// [object String]
//  切片前都是以[object 数据类型]以字符串形式输出,因此要切片
console.log(Object.prototype.toString.call(str).slice(8,-1));// String
console.log(Object.prototype.toString.call(num).slice(8,-1));// Number
console.log(Object.prototype.toString.call(obj).slice(8,-1));// Object
console.log(Object.prototype.toString.call(arr).slice(8,-1));// Array

4. Array.isArray():数组特定的判断方式

Array.isArray() 是专门用于判断一个值是否为数组的方法。在处理复杂的数据结构时,这个方法非常实用,能够准确判断一个值是否是数组类型。

js 复制代码
let arr = [];
Array.isArray(arr); // true

Object.prototype.toString()的底层原理

toString()

在这一串代码中发挥最主要作用的不是Object.prototype,而是toString()。在js内部,给所有的数据都设定了一个\[class]属性,它表明了数据类型,而且不能被修改。并且只有一个方法可以间接查询到它--就是toString()。toString()身上有一个默认行为:如果对象没有自定义的 toString 方法,或者它继承了一个没有自定义的原型链上的 toString 方法,那么将使用默认的 Object.prototype.toString 方法 返回一个字符串,以 "object " 开头,后跟对象的内部 \[\[Class] 属性,最后以 "]" 结尾,并将这三个字符串拼接后返回,就得到了"[object,class]",class就是我们要的数据类型,这个数据类型绝对准确且没法被修改。

call的作用

  1. 需要这样调用的原因主要是对象的toString()方法可能被重写,使用call确保调用的是Object.prototype 上的原始 toString 方法,而不是可能在对象上被修改过的版本。
  2. 因为在toString()的默认行为中,它所获取的那个class的值是toString()内部的this指向的那个对象的值,如果不改变this指向那它默认指向调用toString的prototype。使用call改变this指向我们的目标变量,获取他的class值,最后输出"[object,class]"。
相关推荐
锋行天下10 小时前
DeepSeek写Langgraph就是个大傻逼,一本正经胡说八道
前端·人工智能·后端
jktantan10 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
计算机魔术师11 小时前
Anthropic官方插件被「寄生」,背后是同一类攻击又来了
前端
我命由我1234511 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
key_3_feng11 小时前
评估与对齐:Agent 自我进化的护栏
前端·数据库·agent
程序员大阳12 小时前
副队长JavaScript教程(65)-详解JSON:轻量级数据交换格式
javascript·json·序列化·反序列化·stringify·parse
LaughingZhu12 小时前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
Lank_M12 小时前
抠图结果缩放后边缘发脏,该怪的不是插值
前端
jerrywus12 小时前
Skill、MCP、Workflow、Rules、Memory 有什么区别?拿几次真实开发任务讲清楚
前端·agent·claude
补码缩写12 小时前
canvas 与 sharp 缩放透明图:默认预乘,非预乘得拆通道
前端