究竟谁才是JavaScript类型判断的王者?深度解析四大方法

前言

在JavaScript中,类型判断是一项非常重要的操作。在编写代码时,我们经常需要判断变量的类型,以便根据不同的类型执行不同的逻辑。本文将介绍在JavaScript中如何进行类型判断,以及常见的类型判断方法和注意事项。让我们一起来深入了解吧!

正文

数据类型

聊类型判断前,先让我们看看有哪些类型吧。

javascript 复制代码
//原始数据类型 7种
let str = 'hello' //string
let mun = 123 //number
let flag = false //boolean
let und = undefined //undefined
let nu = null //null
let big = 123n //big number--大整型
//整型最大2**53,v8就不能处理更大的了
let s = Symbol('hello') //Symbol用于定义独一无二的值
let s2 = Symbol('hello')
console.log(s)//Symbol(hello)
console.log(s == s2)//false

这是七种原始类型,其中前五种都是我们比较熟悉的,大整型是为了让v8能够计算更大的值,在number中,v8引擎只能计算到最大值为2的53次方,再大就算不出来了,而大整型就是为了解决这一问题。另一个就是Symbol,这是用来定义独一无二的值,可以用作对象属性名,从而避免属性名冲突的问题。

javascript 复制代码
//引用类型
let obj = {}
let arr = []
let fn = function(){}
let date = new Date()
//等等一些引用类型

判断类型

typeof方法

接下来是用typeof方法判断前面代码块里的数据类型,//后面是判断出的类型

javascript 复制代码
console.log(typeof(str)); //string  
console.log(typeof num); //number
console.log(typeof flag); //boolean
console.log(typeof und); //undefined
console.log(typeof nu); // object bug
console.log(typeof big); //bigint
console.log(typeof s); //symbol

console.log(typeof obj); // object
console.log(typeof arr); // object
console.log(typeof fn); // function
console.log(typeof date); // object 

很明显可以看出来typeof是用来判断原始类型的,除了null其他都能判断出来,引用类型是判断出来的,但有一个特例,就是function类型,这是引用类型唯一能判断出来的。因此,在实际开发中,typeof操作符常常用于简单的类型检测,但对于复杂的类型检测,例如检测数组、函数等,通常需要使用其他方法。那我们怎么判断引用类型呢?

instanceof方法

在JavaScript中,instanceof是一个用于检查对象的原型链中是否存在指定构造函数的方法。它的语法是object instanceof constructor,其中object是要检查的对象,constructor是要检查的构造函数。instanceof的工作原理是检查object的原型链上是否存在constructor.prototype。如果object的原型链存在constructor.prototype,则返回true,否则返回false

举个例子:

javascript 复制代码
function Person(name) {
  this.name = name;
}

let person1 = new Person('Alice');

console.log(person1 instanceof Person); // true
console.log(person1 instanceof Object); // true,因为所有对象都是 Object 的实例

在上面的示例中,person1Person 的实例,因此 person1 instanceof Person 返回 true。同时,由于所有对象都是 Object 的实例,所以 person1 instanceof Object 也返回 true。需要注意的是,instanceof 只能用于检查对象和构造函数之间的关系,不能用于检查基本数据类型。另外,如果对象是通过不同的全局执行上下文创建的,instanceof 可能会返回意外的结果,因为不同执行上下文中的构造函数可能不是同一个对象。

如果我们想手动实现一下instanceof,应该怎么实现呢?看接下来代码

javascript 复制代码
function instanceoF(L,R){ 
    let left = L.__proto__
    let right = R.prototype

    while (left!==null){
        if(left === right) return true
        left = left.__proto__
    }
    return false
}

console.log(instanceoF([],Array));//返回true
console.log(instanceoF([],Object)); //一样

在这个函数中,L 是要检查的对象,R 是要检查的构造函数。

首先将 L 的原型赋值给 left,将 R.prototype 赋值给 right。然后,使用 while 循环遍历 left 的原型链,如果 left 等于 right,则返回 true,表示 LR 的实例。如果 left 的原型链上没有找到 right,则返回 false,表示 L 不是 R 的实例。

在这个函数中,[] instanceof Array 返回 true[] instanceof Object 也返回 true,这与 instanceof 的规则是一致的。因为所有的数组都是 Array 的实例,同时也是 Object 的实例。

Object.prototype.toString.call(xxx)方法

Object.prototype.toString.call(xxx)是一种常用的方法,用于获取一个对象的类型信息。它的工作原理是利用 JavaScript 中所有对象都继承自 Object 的特性,通过调用 Object.prototype.toString 方法来获取对象的类型信息。

具体来说,Object.prototype.toString 方法返回一个表示对象的类型的字符串。当直接调用 toString 方法时,它返回的是对象的类型信息,例如 [object Object][object Array][object Function] 等。然而,通过 call 方法,我们可以改变 this 的指向,从而获取其他对象的类型信息。

javascript 复制代码
// 创建一些不同类型的对象
let arr = [];
let obj = {};
let func = function() {};

// 使用 Object.prototype.toString.call 方法获取它们的类型信息
let arrType = Object.prototype.toString.call(arr);
let objType = Object.prototype.toString.call(obj);
let funcType = Object.prototype.toString.call(func);

// 输出类型信息
console.log(arrType);  // 输出: [object Array]
console.log(objType);  // 输出: [object Object]
console.log(funcType); // 输出: [object Function]

es5.github.io/#x15.2.4.2 这是JavaScript的官方文档,点开里面可以看到该方法的使用规则

然后补充一下,Object.prototype.toString.call 并不是一个单独的方法,而是由两部分组成:Object.prototype.toString 是对象的原型方法,用于返回对象的字符串表示;而 call 是 JavaScript 中用于调用函数的方法。

在这种情况下,call 方法用于改变 toString 方法中的 this 指向。通过使用 call,我们可以将 toString 方法应用到任何对象上,而不仅仅是在该对象上直接调用 toString 方法。这样,我们可以获取任何对象的类型信息,而不仅仅是在全局对象或特定对象上调用 toString 方法时返回的类型信息。

例如,Object.prototype.toString.call(arr) 中的 call 方法将 toString 方法应用于 arr 这个数组对象,以获取它的类型信息。

举个例子如果Object.prototype.toString('123')不加call,那么输出的应该是[object Object],toString方法就是在Object.prototype上的,不管我们传什么值进去,它都是默认这个,而(123).toString()输出'123'。

Array.isArray(arr)方法

Array.isArray(arr) 是 JavaScript 中的一个静态方法,用于检测一个变量是否为数组。如果变量是数组,则该方法返回 true,否则返回 false

这个方法的优点是它能够准确地检测一个变量是否为数组,而不会像 typeof 操作符一样将数组误判为对象。例如,在使用 typeof 操作符时,一个数组会被判断为对象,因为在 JavaScript 中,数组也是对象的一种类型。

下面是一个使用 Array.isArray 方法的示例:

javascript 复制代码
const arr = [1, 2, 3];
const obj = {a: 1, b: 2};
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false

在这个示例中,我们定义了一个数组 arr 和一个对象 obj,然后使用 Array.isArray 方法来检测它们的类型。由于 arr 是一个数组,所以 Array.isArray(arr) 返回 true;而由于 obj 不是一个数组,所以 Array.isArray(obj) 返回 false

需要注意的是,Array.isArray 方法只能用于检测数组类型,而不能用于检测其他类型的对象。如果需要检测其他类型的对象,可以使用 Object.prototype.toString.call 方法来获取对象的类型信息。

总结

这篇文章中,我们详细介绍了 JavaScript 中的四种类型判断方法:typeof 方法、instanceof 方法、Object.prototype.toString.call 方法和 Array.isArray 方法。

  • typeof 方法用于确定变量的基本类型,但对于对象和数组来说并不总是准确,因为它们都会被判断为 "object"。
  • instanceof 方法用于检查对象的原型链,确定一个对象是否是某个构造函数的实例,但在涉及多个全局执行上下文时可能会出现问题。
  • Object.prototype.toString.call 方法是一种准确检测对象类型的方式,可以通过改变 this 的指向来获取对象的类型信息。
  • Array.isArray 方法是一种专门用于检测数组类型的静态方法,能够准确地检测一个变量是否为数组,而不会将数组误判为对象。

总的来说,本文介绍了这些类型判断方法的用法和局限性,并强调了在不同情况下选择合适的方法以确保准确性和可靠性。在你的实际项目中,你更倾向于使用哪种类型判断方法呢?你遇到过哪些关于类型判断的挑战?欢迎分享你的经验和看法!

相关推荐
bysking35 分钟前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓1 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4111 小时前
无网络安装ionic和运行
前端·npm
理想不理想v1 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云1 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205871 小时前
web端手机录音
前端
齐 飞1 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹2 小时前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
aPurpleBerry2 小时前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子2 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js