【必学】浅入深出JS类型判断

前言

当我们在编写JavaScript代码时,了解和正确使用类型判断是非常重要的。JavaScript是一种弱类型语言,变量的类型可以动态改变,因此在处理数据时,我们经常需要进行类型判断以确保代码的正确性和可靠性。

本文将带领读者从基础到高级,深入剖析JavaScript中的类型判断机制,揭开这一重要主题的面纱。

数据类型

JavaScript有七种原始数据类型与四种引用类型,原始数据类型分别是Undefined、Null、Boolean、Number、String、Symbol和BigInt,引用类型分别是对象、数组、函数、日期。

1. typeof

在进行类型判断时,我们可以使用typeof操作符来获取变量的类型。

原始数据类型

js 复制代码
let str = 'hello';
console.log(typeof str);  // "string"

let num = 123;
console.log(typeof num);  // "number"

let flag = true;
console.log(typeof flag); // "boolean"

let und = undefined;
console.log(typeof und);  // "undefined"

let nu = null;
console.log(typeof nu);   // "object"

let big = 123n;
console.log(typeof big);  // "bigint"

let s = Symbol('hello');
console.log(typeof s);    // "symbol"

引用类型

js 复制代码
let obj = {};
console.log(typeof obj);  // "object"

let arr = [];
console.log(typeof arr);  // "object"

let fn = function(){};
console.log(typeof fn);   // "function"

let date = new Date();
console.log(typeof date); // "object"

我们发现typeof null 返回的是object,这是一个历史遗留问题,与语言本身的设计和演变有关。在 JavaScript 的早期版本中,变量的值是由存储在变量存储空间中的标记位来表示的。在 JavaScript 中,所有的对象都表示为32位的字(words),而其中的第一个位被用作类型标签。

  • 对象类型的类型标签是 000
  • null 被认为是一个空对象指针,因此它的类型标签也是 000

因此,typeof null 返回 "object" 是因为在检查变量类型时,JavaScript 会读取存储在变量存储空间中的类型标签,而 null 的类型标签被解释为对象类型。

虽然这个行为是历史遗留问题,但为了保持向后兼容性,JavaScript 的设计者选择保留了这个特性。在现代的 JavaScript 中,为了准确判断变量是否为 null,推荐使用严格相等运算符 ===

js 复制代码
console.log(nu === null) //true

除此之外,我们发现引用类型只能将函数判断为function、将对象判断为object,而数组跟函数也判断为object。所以我们还需要再找一个能进一步判断引用类型的操作符。


2. instanceof

instanceof 操作符用于检查对象是否是特定类(构造函数)的实例。它通过检查对象的原型链来确定对象的类型。如果对象是指定类的实例,则返回 true,否则返回 false

js 复制代码
let obj = {}
console.log(obj instanceof Object); // true 

let arr = []
console.log(arr instanceof Array); // true 

let fn = function(){}
console.log(fn instanceof Function); // true 

let date = new Date()
console.log(date instanceof Date); // true 

所以我们可以通过instanceof,再结合构造函数来判断引用类型。

于是我们可以手写一个instanceof

js 复制代码
function instanceOF(L, R) {
    let left = L.__proto__;    // 初始化变量 left 为实例对象 L 的隐式原型
    let right = R.prototype;    // 初始化变量 right 为构造函数 R 的显示原型 
    while (left !== null) {    // 迭代访问左操作数的原型链,如果不为空则进循环
        if (left === right) {    // 检查当前对象的隐式原型是否与构造函数的显示原型相等
            return true;    // 如果相等,返回 true,表示这个实例对象是这个构造函数创建的 
        } 
        left = left.__proto__;    // 移动到链中的下一个隐式原型 
    } 
    return false;     // 如果没有找到匹配,返回 false 
}
//举例:
console.log(instanceOF([],Array));//true

但是我们在运用instanceof的时候,还会出现一种情况:

js 复制代码
let arr = []
console.log(arr instanceof Object); // true

我们发现,数组也可以被判定为对象,所以当我们要判断一个数据类型是不是对象的时候,用instanceof就不妥,因为数组可以被识别成对象。导致我们判断错误。

那有没有能够直接判断类型的方法?

3. Object.prototype.toString()

官方定义: Object.prototype.toString()当调用toString方法时,将执行以下步骤:

  1. 如果this值未定义,则返回"[object undefined]"
  2. 如果this值为空,则返回"[object null]"
  3. o作为传递this值作为参数的object调用的结果。
  4. classo的内部属性[[Class]]的值。
  5. 返回三个字符串 "[object "class"]" 连接后的String值。

以上为官方规定,在这里就不过多解释,我们直接用就行了。(参考原文Annotated ES5

js 复制代码
let number = 42;
console.log(Object.prototype.toString.call(number)); // "[object Number]"

let str = "Hello";
console.log(Object.prototype.toString.call(str)); // "[object String]" 

let bool = true;
console.log(Object.prototype.toString.call(bool)); // "[object Boolean]"

console.log(Object.prototype.toString.call(null));//'[object Null]'

console.log(Object.prototype.toString.call(undefined));//'[object Undefined]'

let bigint = 123n
console.log(Object.prototype.toString.call(bigint));//'[object BigInt]'

let symbol = Symbol('hello')
console.log(Object.prototype.toString.call(symbol));//'[object Symbol]'

let array = [];
console.log(Object.prototype.toString.call(array)); // "[object Array]"

let date = new Date();
console.log(Object.prototype.toString.call(date)); // "[object Date]" 

var obj = {};
console.log(Object.prototype.toString.call(obj));//'[object Object]'

let func = function() {};
console.log(Object.prototype.toString.call(func)); // "[object Function]"

我们可以用这个方法判断然后数据类型。在这里我们通过使用 call 方法,可以将 this 设置为任何我们想要检查的对象,从而获取该对象的准确类型信息。

我们可以稍加改进,让这个方法更容易为我们所用:

js 复制代码
var s ='thisisstring'

function isType(s) {
    return Object.prototype.toString.call(s).slice(8,-1)
}

if(isType === 'String'){
    //xxx
}

通过isType函数,我们就可以获取变量 s 的类型,并与字符串 'String' 进行比较,其中slice(8,-1)用于截取类型字符串,去除 "[object ""]" 部分。

最后

通过本文的学习,我们不仅深入了解了基本的 typeof 操作符和 instanceof 操作符,还探讨了更为精准的 Object.prototype.toString 方法。这些工具不仅帮助我们在编码过程中避免潜在的错误,还为处理各种复杂的数据结构提供了可靠的手段。

我的Gitee: CodeSpace (gitee.com)

技术小白记录学习过程,有错误或不解的地方还请评论区留言,如果这篇文章对你有所帮助请 "点赞 收藏+关注" ,感谢支持!!

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端
爱敲代码的小鱼9 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax