JS类型检测

144 阅读2分钟

typeof

返回数据类型,包含这7种: numberbooleansymbolstringobjectundefinedfunction。引用类型中的 数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型,没有错,但不是我们想要的结果。

对于typeof null返回object,在《javaScript高级程序设计》(第四版)中这样说道:null被认为是一个空对象的引用

在《你不知道的javascript》(上卷)中这样解释道:这其实知识语言本身的一个bug,实际实际上null本身是基本数据类型,因为不同的对象在底层都表示为二进制,在JavaScipt中二进制前三位为0的话都会判定为object类型,而null的二进制全是0,所以会被判定为object

const Undefined = undefined;
const nu = null;
const num = 20;
const str = "DingShiYi";
const reg = /love/g;
const date = new Date();
const fn = () => {};
const bool = true;
const obj = {};
const sym = Symbol("22");

console.log(typeof Undefined); //undefined
console.log(typeof fn); // function
console.log(typeof bool); // boolean
console.log(typeof sym); // symbol
console.log(typeof num); // number
console.log(typeof str); // string
console.log(typeof reg); // object
console.log(typeof date); // object
console.log(typeof obj); // object
console.log(typeof nu); // object

//对于typeof reg,date,null都被检测为object

constructor

constructor是原型prototype的一个属性,当函数被定义时候,js引擎会为函数添加原型prototype,并且这个prototype中constructor属性指向函数引用。

let num = 23;
let date = new Date();
let str = "啦啦啦";
let reg = new RegExp();
let bool = true;
let fn = function () {
  console.log(233);
};
let udf = undefined;
let nul = null;
let array = [1, 2, 34, 5];
console.log(num.constructor); // [Function: Number]
console.log(date.constructor); // [Function: Date]
console.log(str.constructor); // [Function: String]
console.log(bool.constructor); // [Function: Boolean]
console.log(fn.constructor); // [Function: Function]
console.log(reg.constructor); // [Function: RegExp]
console.log(array.constructor); // [Function: Array]

但是对于null,undefined这种无constructor无法判断

console.log(udf.constructor);//Cannot read property "constructor" of undefined
console.log(nul.constructor);//Cannot read property "constructor" of null

instanceof

instanceof 检测的是原型,A instanceof B检测的是B.prototype是否出现在A的原型链上,instanceof 只能用来判断两个对象是否属于实例关系,而不能判断一个对象实例具体属于哪种类型。例如:

let array = [1, 2, 34, 5];
console.log(array instanceof Array); //true
console.log(Array instanceof Object); //true
console.log(array instanceof Object); //true

简单实现instanceof

function instance_of(L, R) {
  const O = R.prototype;
  if (L === null) {
    return false;
  }
  L = L.__proto__;
  while (true) {
    if (L === null) {
      return false;
    }
    if (L === O) {
      return true;
    }
    L = L.__proto__;
  }
}

instanceof这种方法存在一些问题(原型继承断裂等),之后再进行分享。

Object.prototype.toString.call()

在《你不知道的javaScript》(中卷)中讲到:所有typeof返回值为"object"的对象,都包含一个内部属性[[Class]],我们可以把他看作一个内部的分类,而非传统意义上面向对象的类,这个属性无法直接访问,一般通过Object.prototype.toString(…)来查看。,并且对于基本数据类类型null,undefined这样没有原生构造函数,内部的[[Class]]属性值仍然是NullUndefined

const num = new Number();
const date = new Date();
const str = "啦啦啦";
const reg = new RegExp();
const bool = true;
const fn = function () {
  console.log(233);
};
const udf = undefined;
const nul = null;
const array = [1, 2, 34, 5];
console.log(Object.prototype.toString.call(num));//[object Number]
console.log(Object.prototype.toString.call(date));//[object Date]
console.log(Object.prototype.toString.call(str));//[object String]
console.log(Object.prototype.toString.call(reg));//[object RegExp]
console.log(Object.prototype.toString.call(bool));//[object Boolean]
console.log(Object.prototype.toString.call(fn));//[object Function]
console.log(Object.prototype.toString.call(udf));//[object Undefined]
console.log(Object.prototype.toString.call(nul));//[object Null]
console.log(Object.prototype.toString.call(array));//[object Array]