分析JQ中数据类型检测的方法

197 阅读1分钟

准备

var getProto = Object.getPrototypeOf; //用来获取当前某一个对象的原型
var class2type = {};
var toString = class2type.toString; //Object.prototype.toString
var hasOwn = class2type.hasOwnProperty; //Object.prototype.hasOwnProperty
var fnToString = hasOwn.toString; //函数.toString=>Function.prototype.toString
var ObjectFunctionString = fnToString.call(Object); //=>Function.prototype.toString 执行,把方法中的this更改为Object [相当于]=>Object.toString()  => "function Object() { [native code] }"

检测是否是一个函数

var isFunction = function isFunction(obj) {
    return typeof obj === "function" && typeof obj.nodeType !== "number" &&
        typeof obj.item !== "function";
};

检测是否是一个window对象

var isWindow = function isWindow(obj) {
    // window.window===window 实现了套娃操作
    return obj != null && obj === obj.window;
};

标准的检测数据类型的办法

var arr = ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error", "Symbol"];
arr.forEach(function (name) {
    class2type["[object " + name + "]"] = name.toLowerCase();
});
var toType = function toType(obj) {
    if (obj == null) return obj + "";
    //null和undefined 直接拼接成 字符串
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[toString.call(obj)] || "object" :
        typeof obj;
};

正则优化

var toType = function toType(obj) {
    if (obj == null) return obj + "";
    var reg = /^\[object ([a-zA-Z0-9]+)\]$/i;
    return typeof obj === "object" || typeof obj === "function" ?
        reg.exec(toString.call(obj))[1].toLowerCase() :
        typeof obj;
};

检测是否为数组或者类数组

var isArrayLike = function isArrayLike(obj) {
    var length = !!obj && "length" in obj && obj.length,
        type = toType(obj);
    if (isFunction(obj) || isWindow(obj)) return false;
    return type === "array" || length === 0 ||
        typeof length === "number" && length > 0 && (length - 1) in obj;
};

检测是否为纯粹的对象「直属类是Object || Object.create(null)」

var isPlainObject = function isPlainObject(obj) {
    var proto, Ctor;
    if (!obj || toString.call(obj) !== "[object Object]") return false;
    proto = getProto(obj);
    if (!proto) return true;
    Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
    return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
};

检测是否是空对象

var isEmptyObject = function isEmptyObject(obj) {
    var keys = Object.keys(obj);
    if (typeof Symbol !== "undefined") keys = keys.concat(Object.getOwnPropertySymbols(obj));
    return keys.length === 0;
};

检测是否是数字

var isNumeric = function isNumeric(obj) {
    var type = toType(obj);
    return (type === "number" || type === "string") && !isNaN(obj);
};