【JavaScript】类型判断

145 阅读3分钟

类型判断

简单数据类判断

typeof

  • typeof可以准确判断除了null以外的基本数据类型

  • typeof判断引用数据类型,除了function以外,其他的都返回object

typeof是通过将值转换成二进制来判断类型的,对于二进制前三位是 0 的统一识别为对象

而所有的引用类型二进制前三位都是0

同时,null的二进制全是0

来点代码看看吧:

let s = 'hello'   
let n = 123  
let f = true   
let u = undefined  
let sy = Symbol(1)  
let b = 1231231231n  
let nu = null 

console.log(typeof(s));  // string
console.log(typeof(n));  // number
console.log(typeof(f));  // boolean
console.log(typeof(u));  // undefined
console.log(typeof sy);  // symbol
console.log(typeof b);   // bigint
console.log(typeof nu);  // object  --不能对null进行识别

接下来看看复杂数据类型中使用typeof的表现:

let arr = []
let obj = {}
let date = new Date()
let set = new Set()
let map = new Map()
let fun = function() {}

console.log(typeof arr);   // object
console.log(typeof obj);   // object
console.log(typeof date);  // object
console.log(typeof set);   // object
console.log(typeof map);   // object
console.log(typeof fun);   // function

可以看到,typeof对除了function以外的所有复杂数据类型都束手无策统统输出object

复杂数据类型

instanceof

  • 能准确判断引用类型,不能判断基本数据类型

  • 需要使用形如:s instnceof Class

  • 判断的机制是:通过对象的隐式原型链来查找是否存在某一项等于右边的 prototype

上代码:

let s = 'hello'   // string
let n = 123  // number
let f = true   // boolean
let u = undefined  // undefined
let nu = null  // object
let sy = Symbol(1)  // symbol
let b = 1231231231n  // bigint



let obj = {}
let fun = function() {}
let date = new Date()
let set = new Set()
let map = new Map()

// 复杂数据类型统统拿下
console.log(obj instanceof Object);    // true
console.log(fun instanceof Function);  // true
console.log(date instanceof Date);     // true
console.log(set instanceof Set);       // true
console.log(map instanceof Map);       // true

// 简单数据类型全军覆没
console.log(s instanceof String)    // false
console.log(n instanceof Number)    // false
console.log(f instanceof Boolean)   // false
console.log(sy instanceof Symbol)   // false
console.log(b instanceof BigInt)    // true

手写instanceof

function myInstanceof(L, R) {
  L = L.__proto__

  while(L) {
    if (L === R.prototype) {
      return true
    }
    L = L.__proto__
  }
  return false
}

console.log(myInstanceof([], Array));   // 检验
console.log(myInstanceof([], Object));  // 检验

追问:根据instanceof机制,以下代码的输出内容是什么?

let arr = []
console.log(arr instanceof Array)
console.log(arr instanceof Object) 

聪明的同学应该知道,两个代码的结果都是true,根据原型链的关系,Array也是属于Object的。

图解:原型链及原型链详解

原型链

既然数组和对象这么难搞

那么接下来我们介绍一个万金油的判断方法

万能大法

Object.prototype.toString.call()

  1. 如果this value未定义 ,则返回[object Undefined]
  2. 如果this valuenull,则返回[object Null]
  3. O为调用ToObject的结果,将this值作为参数传递
  4. classO[Class]内部属性的值
  5. 返回String值,该值是[object class]

代码示例:

Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call("hello"); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(function(){}); // "[object Function]"
// 注意的是,Object.prototype.toString.call 方法返回的字符串格式为 "[object 类型]"

// 封装
function typeOf(data) {
  return Object.prototype.toString.call(data).slice(8, -1);  //修改输出格式
}

// 测试
console.log(typeOf(1)); // Number
console.log(typeOf("1")); // String
console.log(typeOf(true)); // Boolean
console.log(typeOf(null)); // Null
console.log(typeOf(undefined)); // Undefined
console.log(typeOf(Symbol(1))); // Symbol
console.log(typeOf({})); // Object
console.log(typeOf([])); // Array
console.log(typeOf(function () {})); // Function
console.log(typeOf(new Date())); // Date
console.log(typeOf(new RegExp())); // RegExp

isXXX方法

  • Array.isArray方法可以判断一个对象是否为数组
  • Number.isNaN可以判断一个值是否为NaN
  • Number.isFinite可以判断一个值是否为有限数
console.log(Array.isArray([1, 2, 3])); // true
console.log(Array.isArray({})); // false
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(123)); // false
console.log(Number.isNaN("hello")); // false
console.log(Number.isFinite(123)); // true
console.log(Number.isFinite("hello")); // false
console.log(Number.isFinite(Infinity)); // false

总结

  1. typeof可以准确地判断出基本类型,但是对于引用类型除function之外返回的都是object

  2. 已知是引用类型的情况可以选用instanceof进行具体类型的判断:instanceof是基于原型链的

  3. Object.prototype.toString.call()通用但很繁琐