【必学】浅入深出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)

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

相关推荐
清灵xmf17 分钟前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据24 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_3901617732 分钟前
防抖函数--应用场景及示例
前端·javascript
334554321 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript