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";
}