UNPKG

@ivujs/i-utils

Version:

前端模块化 JavaScript 工具库

447 lines (445 loc) 12.9 kB
/** * @module 校验 */ /** * 判断是整数 * @param {*} value 参数 * @returns {boolean} result 返回结果 */ function isInteger(value) { return Number.isInteger(value); } /** * 判断是小数 * @param {*} value 参数 * @returns {boolean} result 返回结果 */ function isDecimal(value) { return /^\d+\.\d+$/.test(value); } /** * 判断类型是数字 Number * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isNumber(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Number"; } /** * 判断类型是字符串 String * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isString(value) { return Object.prototype.toString.call(value).slice(8, -1) === "String"; } /** * 判断类型是数组 Array * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isArray(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Array"; } /** * 判断类型是对象 Object * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isObject(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Object"; } /** * 判断类型是布尔 boolean * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isBoolean(value) { return Object.prototype.toString.call(value).slice(8, -1) === "boolean"; } /** * 判断类型是日期 Date * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isDate(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Date"; } /** * 判断类型是函数 Function * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isFunction(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Function"; } /** * 判断类型是函数字符串 FunctionString * @description 支持普通函数,异步函数,箭头函数 * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isFunctionString(value) { if (value) { try { const fn = new Function(`return ${value}`)(); return typeof fn === "function"; } catch (e) { // 如果发生错误,比如语法错误,那么这不是一个有效的函数 return false; } } else { return false; } } /** * 判断类型是异步函数 AsyncFunction * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isAsyncFunction(value) { return Object.prototype.toString.call(value).slice(8, -1) === "AsyncFunction"; } /** * 判断类型是 Symbol * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isSymbol(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Symbol"; } /** * 判断类型是正则 RegExp * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isRegExp(value) { return Object.prototype.toString.call(value).slice(8, -1) === "RegExp"; } /** * 判断类型是错误 Error * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isError(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Error"; } /** * 判断类型是 Promise * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isPromise(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Promise"; } /** *判断类型是 Map * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isMap(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Map"; } /** * 判断类型是 WeakMap * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isWeakMap(value) { return Object.prototype.toString.call(value).slice(8, -1) === "WeakMap"; } /** * 判断类型是 Set * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isSet(value) { return Object.prototype.toString.call(value).slice(8, -1) === "Set"; } /** * 判断类型是 WeakSet * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isWeakSet(value) { return Object.prototype.toString.call(value).slice(8, -1) === "WeakSet"; } /** * 判断类型是 BigInt * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isBigInt(value) { return Object.prototype.toString.call(value).slice(8, -1) === "BigInt"; } /** * 判断类型是 Json * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isJson(value) { try { JSON.parse(value); return true; } catch (error) { return false; } } /* 数据值校验 */ /** * 判断值为真 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isTrue(value) { return !isFalse(value); } /** * 判断值为假 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isFalse(value) { return (value === undefined || value === null || value === "undefined" || value === "null" || value === 0 || value === false || isNaN(value)); } /** * 判断非数字 * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isNaN(value) { return (value == null || typeof value === "boolean" || Array.isArray(value) || value === "" || Number.isNaN(Number(value))); } /** * 判断是数字 * @description 等同于isNumber() * @param {*} value 参数 * @returns {boolean} 返回结果 */ function isNotNaN(value) { return !isNaN(value); } /** * 判断对象为空 * @description 判断值是否为空,如果对象初始化了值则不为空 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isNull(value) { return value === undefined || value === null || value === ""; } /** * 判断对象不为空 * @description 判断值是否为空,如果对象初始化了值则不为空 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isNotNull(value) { return !isNull(value); } /** * 判断值为空 * @description 判断是否是有意义不为空的值,如果值是{},[]空的数据则为空 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isEmpty(value) { if (isNull(value)) return true; if (typeof value === "string" || Array.isArray(value)) { return value.length === 0; } if (typeof value === "object") { if (value instanceof Map || value instanceof Set) { return value.size === 0; } if (value instanceof Date || value instanceof RegExp || value instanceof Error) { return false; } return Object.keys(value).length === 0; } return false; } /** * 判断值不为空 * @description 判断是否是有意义不为空的值,如果值是{},[]空的数据则为空 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isNotEmpty(value) { return !isEmpty(value); } /** * 判断值是空白的 * @description 同时会校验空值,空对象,以及空白符号 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isBlank(value) { return isEmpty(value) || /^\s*$/.test(value); } /** * 判断值不是空白的 * @description 同时会校验空值,空对象,以及空白符号 * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isNotBlank(value) { return !isBlank(value); } /** * 判断值是undefined * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isUndefined(value) { return value === undefined; } /** * 判断值不是undefined * @param {*} value 校验的参数 * @returns {boolean} 返回结果 */ function isNotUndefined(value) { return !isUndefined(value); } /* 数据比较 */ /** * 判断两个值是否相等 * @param {*} value1 参数1 * @param {*} value2 参数2 * @returns {boolean} 返回结果 */ function equals(value1, value2) { return Object.is(value1, value2); } /** * 判断两个值是否相等(忽略大小写) * @param {*} value1 参数1 * @param {*} value2 参数2 * @returns {boolean} 返回结果 */ function equalsIgnoreCase(value1, value2) { return Object.is(value1.toLowerCase(), value2.toLowerCase()); } /** * 深度对比数据 * @description 可以对比任意数据,对象、数组、日期等也可深度对比,对象不区分先后顺序 * @param {*} x 数据1 * @param {*} args 数据2 * @returns {boolean} 返回对比结果 */ function deepCompare(x, ...args) { let leftChain = []; let rightChain = []; // 核心对比函数(添加严格类型标注) const compare2Objects = (xObj, yObj) => { // 1. 处理 NaN 特殊场景(NaN === NaN 返回 false,需单独判断) if (Number.isNaN(xObj) && Number.isNaN(yObj)) { return true; } // 2. 原始类型/引用同一对象 直接对比 if (xObj === yObj) { return true; } // 3. 特殊内置对象对比(函数/日期/正则/包装对象) const typeOfX = typeof xObj; const typeOfY = typeof yObj; // 函数对比:通过 toString 比较内容 if (typeOfX === "function" && typeOfY === "function") { return xObj.toString() === yObj.toString(); } // 日期对象对比:时间戳一致则相等 if (xObj instanceof Date && yObj instanceof Date) { return xObj.getTime() === yObj.getTime(); } // 正则对象对比:源文本+标志位一致则相等 if (xObj instanceof RegExp && yObj instanceof RegExp) { return xObj.source === yObj.source && xObj.flags === yObj.flags; } // 字符串/数字包装对象对比 if ((xObj instanceof String && yObj instanceof String) || (xObj instanceof Number && yObj instanceof Number)) { return xObj.toString() === yObj.toString(); } // 4. 非对象类型(排除上述特殊类型后)直接返回 false if (!(xObj instanceof Object && yObj instanceof Object)) { return false; } // 5. 原型链/构造函数校验 if (xObj.isPrototypeOf(yObj) || yObj.isPrototypeOf(xObj)) { return false; } if (xObj.constructor !== yObj.constructor) { return false; } if (xObj.prototype !== yObj.prototype) { return false; } // 6. 循环引用检测(避免无限递归) if (leftChain.includes(xObj) || rightChain.includes(yObj)) { return false; } // 7. 遍历对象属性,对比键存在性和类型 const xObjKeys = Object.keys(xObj); const yObjKeys = Object.keys(yObj); // 先对比属性数量(数量不同直接不相等) if (xObjKeys.length !== yObjKeys.length) { return false; } // 遍历所有属性,校验存在性、类型、值 for (const p of yObjKeys) { if (Object.prototype.hasOwnProperty.call(xObj, p) !== Object.prototype.hasOwnProperty.call(yObj, p)) { return false; } const xProp = xObj[p]; const yProp = yObj[p]; if (typeof xProp !== typeof yProp) { return false; } } // 深度对比属性值 for (const p of xObjKeys) { const xProp = xObj[p]; const yProp = yObj[p]; if (typeof xProp === "object" || typeof xProp === "function") { leftChain.push(xObj); rightChain.push(yObj); if (!compare2Objects(xProp, yProp)) { return false; } leftChain.pop(); rightChain.pop(); } else { if (xProp !== yProp) { return false; } } } return true; }; // 边界处理:参数数量不足时的兜底 if (arguments.length < 2) { console.warn("deepCompare 需要至少两个对比参数"); return true; } // 遍历所有传入的参数(支持对比多个值) for (const y of args) { leftChain = []; rightChain = []; if (!compare2Objects(x, y)) { return false; } } return true; } export { deepCompare, equals, equalsIgnoreCase, isArray, isAsyncFunction, isBigInt, isBlank, isBoolean, isDate, isDecimal, isEmpty, isError, isFalse, isFunction, isFunctionString, isInteger, isJson, isMap, isNaN, isNotBlank, isNotEmpty, isNotNaN, isNotNull, isNotUndefined, isNull, isNumber, isObject, isPromise, isRegExp, isSet, isString, isSymbol, isTrue, isUndefined, isWeakMap, isWeakSet };