js类型判断

5 阅读1分钟

Type

在js中,有两套类型判定系统, js有6种数据类型, undefined, null, string, booleam, function, object, 基本数据类型可以通过typeof判断, 但是当涉及到对象类型的时候, typeof 就不够用了, js提供了instanceof来检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。还可以通过借用Object.prototype.toString这个方法判断类型,Object.prototype.toString,通过借用这个方法我们可以统一判断基本字符串和对象类型, 现有的3种方法可以组合起来判断类型,但是不够好用, 我们可以扩写成一个方法

const class2type = "Boolean Number String Function Array Date RegExp Object Error Symbol Promise Map Set".split(" ").reduce((acc, curr) => (acc[`[object ${curr}]`] = curr.toLowerCase(), acc), {});


const toString = Object.prototype.toString;

const toType = function (obj) {
  if (obj == null) {
    return obj + "";
  }

  return typeof obj === "object" ? class2type[toString.call(obj)] : typeof obj;
}

console.log(toType({}));
console.log(toType(/s/));
console.log(toType(() => {}));
console.log(toType(Promise.resolve()));
console.log(toType(new Map()));
console.log(toType(new Set()));

我们可以继续义了Symbol.toStringTag属性的对象视作自定义类型,把其也纳class2Type,让这个函数能够判断拥有Symbol.stringTag属性的自定义对象类型。

const class2type = "Boolean Number String Function Array Date RegExp Object Error Symbol Promise Map Set".split(" ").reduce((acc, curr) => (acc[`[object ${curr}]`] = curr.toLowerCase(), acc), {});


const toString = Object.prototype.toString;

const toType = function (obj) {
  if (obj == null) {
    return obj + "";
  }

  if (typeof obj !== "object") {
    return typeof obj;
  }

  let strTag = toString.call(obj);

  if (!class2type[strTag]) {
    class2type[strTag] = strTag.slice(strTag.indexOf(" ") + 1, strTag.length - 1);
  }

  return class2type[strTag]
}

console.log(toType({}));
console.log(toType(/s/));
console.log(toType(() => {}));
console.log(toType(Promise.resolve()));
console.log(toType(new Map()));
console.log(toType(new Set()));

const arr = { [Symbol.toStringTag]: "这是arr类型" };

console.log(toType(arr));
console.log(class2type, 'class2Type');

isPlainObject

字面量对象就是一个纯对象, 判断一个对象是否为纯对象,用于和其它复杂对象做区分,比如实例出来的对象,纯象可以在JSON.stringify操作前过滤一遍判断是否可以安全的处理,而且在做对象的深拷贝的时候,纯对象也可以避免拷贝一些原型链上的属性

const toString = Object.prototype.toString;
const getProto = Object.getPrototypeOf;
const hasOwn = Object.hasOwn;

const isPlainObject = (obj) => {
  if (!obj || toString.call(obj) !== "[object Object]") {
    return false;
  }

  let proto = getProto(obj);

  //Object.create(null);
  if (!proto) {
    return true;
  }
  
  return proto === Object.prototype;

}
console.log(isPlainObject({}));
console.log(isPlainObject(Object.create(null))); 

class Test {}
const tesIns = new Test();
console.log(isPlainObject(tesIns));

isWindow

const isWindow = (obj) => {
return obj && obj.window === obj && obj.window === window);
};

isArrayLike

const hasOwn = Object.hasOwn;
 
const isArrayLike = function (obj) {

  if (!obj || typeof obj === "function" || isWindow(obj)) {
    return false;
  }

  return typeof obj.length === "number";
}