likes
comments
collection
share

深入探索JavaScript类型奥秘:全方位掌握类型判断艺术

作者站长头像
站长
· 阅读数 50

前言

在JavaScript这门动态类型语言中,由于其灵活性,变量的类型可以在运行时改变,这虽赋予了开发人员极大的自由度,但也带来了潜在的类型不确定问题。因此,了解并掌握类型判断变得尤为重要。它不仅能帮助我们避免类型错误,还能提升代码的健壮性和可维护性。本篇将深入探讨JavaScript中的类型判断方法,从传统的typeof操作符、instanceof关键字到ES6引入的更精细的Object.prototype.toString.call()等方法,以及利用最新的一些方法等进行精确类型检测的技巧,为你的JavaScript之旅保驾护航。

1.typeof

  1. typeof 可以判断除null之外的所有原始类型
  2. 除了function其他所有的引用类型都会被判断为object
  3. typeof是通过将值转换为二进制后判断前三位是否为0,是则为object
let s = '123'
let n = 123
let f = true
let u = undefined
let nu = null
let sy = Symbol(123) // symbol
let big = 1234n // bigint

let obj = {}
let arr = []
let fn = function () { }
let date = new Date()

console.log(typeof (s))//string
console.log(typeof (n))//number
console.log(typeof (f))//boolean
console.log(typeof (u))//undefined
console.log(typeof (nu))//object
console.log(typeof (sy))//symbol
console.log(typeof (big))//bigint
console.log(typeof (obj))//object
console.log(typeof (arr))//object
console.log(typeof (fn))//function
console.log(typeof (date))//object

之所以null会被判定为object,是因为null在设计时的二进制表达就是一连串的0,而typeof是根据二进制来判断的,所有的引用类型的前三位都是0,所有的基本类型的前三位一定不为0,因此null会被错误判断为对象,而function不会被判断为对象,而是更为精准的function。

2.instanceof

2.1 instanceof 说明

  1. 只能判断引用类型
  2. 通过原型链查找来判断
let s = '123'
let n = 123
let f = true
let u = undefined
let nu = null
let sy = Symbol(123) // symbol
let big = 1234n // bigint

let obj = {}
let arr = []
let fn = function () { }
let date = new Date()


console.log(s instanceof Number)//false
console.log(obj instanceof Object)//true
console.log(arr instanceof Object)//true
console.log(arr instanceof Array)//true
console.log(fn instanceof Object)//true
console.log(fn instanceof Function)//true
console.log(date instanceof Object)//true

instanceof并不能判断基本类型的结果,而对引用类型的判断是比较准确的,我们可以发现,数组既属于数组,又属于对象,当看见这种现象时,想必我们一定可以想到原型。

2.2手写一个instanceof

我们通过手写一个instanceof来了解其底层原理

function myinstanceof(L, R) {
  while (L !== null) {
    if (L.__proto__ === R.prototype) {
      return true
    }
    L = L.__proto__
  }
  return false
}
console.log(myinstanceof([], Array))//true
console.log(myinstanceof([], Object))//true
console.log(myinstanceof({}, Array))//false

3. Object.prototype.toString()

3.1方法简介

这个方法可以用来准确的判断一个数据的类型,相比前面两种方法会更优化。

首先明确一点,我们是不能直接 Object.prototype.toString(xxx)去使用的,我们来看JavaScript官方给出的这个方法的解释。

深入探索JavaScript类型奥秘:全方位掌握类型判断艺术

深入探索JavaScript类型奥秘:全方位掌握类型判断艺术

因此我们要明确如果我们不去显式绑定的话,this 通常会默认指向全局对象(在浏览器环境中是 window,在Node.js环境中是 global)这样直接调用就是[object Object]。

深入探索JavaScript类型奥秘:全方位掌握类型判断艺术

以上答案均为相同的[object Object]。

3.2 手写一个mycall

深入探索JavaScript类型奥秘:全方位掌握类型判断艺术

我们知道,这个方法要想使用,我们必须使它的this指向传入的参数,那么我们就自己手写一个mycall函数来改变this指向。

首先我们的方法被foo函数调用,根据隐式绑定规则,mycall里的this指向foo,这个时候我们首先判断this是不是一个函数,如果不是,我们应该报错,然后我们创建一个独一无二的属性名,把foo函数作为传入参数的属性值(这个时候foo里this指向为传入参数),然后调用此函数,最后删除foo这个属性。我们就完成了改变函数里的this指向还同时调用了函数。当然其实可以传入更多参数,我们这里假定不需要传入参数。

3.3 深入了解Object.prototype.toString()和Object.prototype.toString.call()

现在我们就可以来总结一下这个方法了,首先不可以直接用,因为这个时候的this指向全局,并不指向传入的参数,如果我们通过call来改变指向,这个时候的this就是指向传入参数,我们就可以进一步判断:

  1. 首先判断this是不是为undefined,是则返回[object Undefined]
  2. 判断this是不是为null,是则返回[object Null]
  3. 把o作为ToObject的结果,关于这个函数大家可以看上方内容。
  4. 定义一个class作为o内部属性[[class]] 的值
  5. 返回由'[object' 和class 和 ']'组成的字符串
let s = '123'
let n = 123
let f = true
let u = undefined
let nu = null
let sy = Symbol(123) // symbol
let big = 1234n // bigint

let obj = {}
let arr = []
let fn = function () { }
let date = new Date()

console.log(Object.prototype.toString.call(s))//[object String]
console.log(Object.prototype.toString.call(n))//[object Number]
console.log(Object.prototype.toString.call(f))//[object Boolean]
console.log(Object.prototype.toString.call(u))//[object Undefined]
console.log(Object.prototype.toString.call(nu))//[object Null]
console.log(Object.prototype.toString.call(sy))//[object Symbol]
console.log(Object.prototype.toString.call(big))//[object BigInt]
console.log(Object.prototype.toString.call(obj))//[object Object]
console.log(Object.prototype.toString.call(arr))//[object Array]
console.log(Object.prototype.toString.call(fn))//[object Function]
console.log(Object.prototype.toString.call(date))//[object Date]

我们可以看见结果非常正确!

4 Array.isArray()

Array.isArray() 是JavaScript中的一个内置方法,用于判断给定的变量是否为数组的实例。如果该变量是数组,该方法返回 true;如果不是数组,则返回 false。这个方法可以帮助你在编写代码时更准确地处理数据类型,特别是在需要对不同类型的变量进行条件判断时非常有用。

let arr = [1, 2, 3];
let str = "这不是一个数组";

console.log(Array.isArray(arr)); // 输出: true,因为arr是一个数组
console.log(Array.isArray(str)); // 输出: false,因为str不是一个数组
转载自:https://juejin.cn/post/7370344254693490697
评论
请登录