@pkt/utils
Version:
1,069 lines (1,055 loc) • 28.2 kB
JavaScript
import clone from 'just-clone';
/**
* Check if value is a function.
*/
function isFunction(value) {
return typeof value === 'function';
}
/**
* Check if value is a valid JSON.
*/
function isJson(value) {
try {
JSON.parse(value);
return true;
}
catch (e) {
return false;
}
}
/**
* Check if value is a string primitive.
*/
function isString(value) {
return objToStr(value) === '[object String]';
}
/**
* Check if value is a type primitive
*/
function is(value, type) {
return objToStr(value) === `[object ${type}]`;
}
/**
* Check if value is a string primitive.
*
* isNonEmptyString(''); // -> false
*/
function isNonEmptyString(value) {
return typeof value === 'string' && value !== '';
}
/**
* Check if value is undefined.
*
* isUndefined(void 0); // -> true
*/
function isUndefined(value) {
return value === undefined;
}
function isUndefinedOrEmptyString(value) {
return value === undefined || value === '';
}
/**
* Check if value is an Null.
*/
function isNull(value) {
return value === null;
}
/**
* Check if value is null or undefined, the same as value == null.
*
* isNullOrUndefined(null); // -> true
* isNullOrUndefined(undefined); // -> true
* isNullOrUndefined(void 0); // -> true
*/
function isNullOrUndefined(obj) {
return obj === null || obj === undefined;
}
/**
* Check if value is the language type of Object.
*
* isObject({}); // -> true
* isObject([]); // -> true
*/
function isObject(value) {
return value instanceof Object;
}
function isObjectAndNotArray(value) {
return isObject(value) && !Array.isArray(value);
}
function isObjectAndNotArrayNotNode(value) {
return isObjectAndNotArray(value) && !isNode(value);
}
function isNode(value) {
return value instanceof Node;
}
/**
* exists
* @param obj
* @returns boolean
*/
function exists(obj) {
return !isNullOrUndefined(obj);
}
/**
* Check if value is classified as a Number primitive or object.
*/
function isNum(value) {
return /^((-?\d+\.\d+)|(-?\d+)|(-?\.\d+))$/.test(value.toString());
}
/**
* Checks if value is classified as a Integer.
*/
function isInt(value) {
return isNum(value) && value % 1 === 0;
}
/**
* Checks if value is classified as a Decimal.
*/
function isDecimal(value) {
return isNum(value) && !isInt(value);
}
/**
* Check if number is odd.
*/
function isOdd(value) {
if (!isInt(value)) {
return false;
}
return value % 2 !== 0;
}
/**
* Check if value is an IdCard.
*/
function isIdCard(value) {
return typeof value === 'string' && /(^\d{15}$)|(^\d{17}([0-9]|X)$)/i.test(value);
}
/**
* Check if value is an Mobile.
*/
function isMobile(value) {
return (typeof value === 'string' &&
/^(0|\+?86|17951)?(13[0-9]|14[579]|15[0-9]|16[6]|17[1-3,5-8]|18[0-9]|19[189])[0-9]{8}$/.test(value));
}
/**
* Check if value is an url address.
*/
function isUrl(value) {
// eslint-disable-next-line no-useless-escape
return /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/.test(value);
}
/**
* Check if value is an IP address.
*/
function isIp(value) {
const v4 = '(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}';
const regV4 = new RegExp('^'.concat(v4, '$'));
const v6seg = '[a-fA-F\\d]{1,4}';
const v6 = [
'(',
'(?:'.concat(v6seg, ':){7}(?:').concat(v6seg, '|:)|'),
'(?:'.concat(v6seg, ':){6}(?:').concat(v4, '|:').concat(v6seg, '|:)|'),
'(?:'.concat(v6seg, ':){5}(?::').concat(v4, '|(:').concat(v6seg, '){1,2}|:)|'),
'(?:'
.concat(v6seg, ':){4}(?:(:')
.concat(v6seg, '){0,1}:')
.concat(v4, '|(:')
.concat(v6seg, '){1,3}|:)|'),
'(?:'
.concat(v6seg, ':){3}(?:(:')
.concat(v6seg, '){0,2}:')
.concat(v4, '|(:')
.concat(v6seg, '){1,4}|:)|'),
'(?:'
.concat(v6seg, ':){2}(?:(:')
.concat(v6seg, '){0,3}:')
.concat(v4, '|(:')
.concat(v6seg, '){1,5}|:)|'),
'(?:'
.concat(v6seg, ':){1}(?:(:')
.concat(v6seg, '){0,4}:')
.concat(v4, '|(:')
.concat(v6seg, '){1,6}|:)|'),
'(?::((?::'.concat(v6seg, '){0,5}:').concat(v4, '|(?::').concat(v6seg, '){1,7}|:))'),
')(%[0-9a-zA-Z]{1,})?'
].join('');
const regV6 = new RegExp('^'.concat(v6, '$'));
return regV4.test(value) || regV6.test(value);
}
/**
* Loosely validate an email address.
*/
function isEmail(value) {
const regEmail = /.+@.+\..+/;
return regEmail.test(value);
}
function objToStr(val) {
const ObjToStr = Object.prototype.toString;
return ObjToStr.call(val);
}
/**
* 数组转Json {'':''}
* @param arr 数组
* @param key 字段
*/
function arrToJson(arr, key = 'id') {
const pos = {};
if (isNonEmptyString(key) === false) {
for (const no of arr) {
pos[no] = no;
}
return pos;
}
for (const no of arr) {
pos[no[key]] = no;
}
return pos;
}
/**
* 数组转Json(json嵌套数组) {'':[]}
* @param arr 数组
* @param key 字段
*/
function arrToJsonArr(arr, key = 'id') {
const pos = {};
for (const x of arr) {
if (!pos[x[key]]) {
pos[x[key]] = [];
}
pos[x[key]].push(x);
}
return pos;
}
/**
* json转数组
* @param value object数组
*/
function jsonToArr(value) {
if (!isObject(value)) {
return [];
}
const temps = [];
let temp = {};
for (const key in value) {
if (value.hasOwnProperty(key)) {
temp = value[key];
temps.push(temp);
}
}
return temps;
}
/**
* Convert value to a string.
*/
function toString(value) {
return isNullOrUndefined(value) ? '' : value.toString();
}
function toBoolean(value, defaultValue = false) {
return isNullOrUndefined(value) ? defaultValue : `${value}` !== 'false';
}
function toNumber(value, fallbackValue = 0) {
return !isNaN(parseFloat(value)) && !isNaN(Number(value))
? Number(value)
: fallbackValue;
}
/**
* Returns the number of elements in the array by returning `value.length`.
*
* toLength([]); //=> 0
* toLength([1, 2, 3]); //=> 3
*
* toLength(null); //=> NaN
* toLength(undefined); //=> NaN
*/
function toLength(value) {
if (Array.isArray(value) === true || isString(value) === true) {
return value.length;
}
return NaN;
}
/**
* Convert value to a Hash.
* return string of length 5
*/
function toHash(value) {
const length = toLength(value);
if (isNaN(length) === true) {
return '';
}
const I64BIT_TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-'.split('');
let hashNu = 5381;
let i = length - 1;
try {
if (isString(value) === true) {
for (; i > -1; i--) {
hashNu += (hashNu << 5) + value.charCodeAt(i);
}
}
else {
for (; i > -1; i--) {
hashNu += (hashNu << 5) + value[i];
}
}
let rvalue = hashNu & 0x7fffffff;
let retValue = '';
do {
retValue += I64BIT_TABLE[rvalue & 0x3f];
} while ((rvalue >>= 6));
return retValue;
}
catch (error) {
return '';
}
}
/**
* 复选框(全选/多选)
* @param id 唯一标识(默认ID)
*/
function checkBox(id = 'id') {
const checkbox = {
isSelectAll: false,
/**
* 选中数量
*/
selectCount: 0,
/**
* 获取已选中的ID数据
*/
getIDS() {
const selects = [];
const selectvalue = checkbox.select.value;
for (const key in selectvalue) {
// eslint-disable-next-line no-prototype-builtins
if (selectvalue.hasOwnProperty(key)) {
if (selectvalue[key]) {
selects.push(key);
}
}
}
return selects;
},
/**
* 清空所有选择
*/
clear() {
checkbox.isSelectAll = false;
checkbox.selectCount = 0;
checkbox.select.value = {};
},
/**
* 单选
*/
select: {
change(data) {
const selects = veriArr(data);
if (selects.length < 1) {
checkbox.isSelectAll = false;
return;
}
const counts = [];
const selectvalue = checkbox.select.value;
for (const key in selectvalue) {
if (selectvalue.hasOwnProperty(key)) {
if (selectvalue[key]) {
counts.push(key);
}
}
}
checkbox.isSelectAll = selects.length === counts.length;
checkbox.selectCount = counts.length;
},
/**
* 选择的数据
* 格式 value: { ID:{true}, ID:{false}}
*/
value: {}
},
/**
* 全选
*/
selectAll: {
change(data) {
const selects = veriArr(data);
if (selects.length < 1) {
checkbox.isSelectAll = false;
return;
}
// 全选
if (checkbox.isSelectAll) {
for (let i = selects.length; i--;) {
checkbox.select.value[selects[i][id]] = true;
}
}
else {
// 取消全选
for (let i = selects.length; i--;) {
delete checkbox.select.value[selects[i][id]];
}
}
checkbox.selectCount = jsonToArr(checkbox.select.value).length;
}
}
};
return checkbox;
}
function veriArr(data) {
if (!data) {
return [];
}
if (Array.isArray(data)) {
return data;
}
if (isObject(data)) {
return jsonToArr(data);
}
return [];
}
/**
* A no-operation function.
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
function noop() { }
/**
*
* 获取浏览器的语言
*
* @returns 例如 `"zh"`
*/
function getBrowserLang() {
if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
return undefined;
}
// to avoid compiler mis-error.
const w = window;
let browserLang = w.navigator.languages ? w.navigator.languages[0] : null;
browserLang =
browserLang || w.navigator.language || w.navigator.browserLanguage || w.navigator.userLanguage;
if (browserLang.indexOf('-') !== -1) {
browserLang = browserLang.split('-')[0];
}
if (browserLang.indexOf('_') !== -1) {
browserLang = browserLang.split('_')[0];
}
return browserLang;
}
/**
*
* 获取浏览器的语言
*
* @returns 例如 `"zh-CN"`
*/
function getBrowserCultureLang() {
if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
return undefined;
}
// to avoid compiler mis-error.
const w = window;
let browserCultureLang = w.navigator.languages ? w.navigator.languages[0] : null;
browserCultureLang =
browserCultureLang ||
w.navigator.language ||
w.navigator.browserLanguage ||
w.navigator.userLanguage;
return browserCultureLang;
}
/**
* 列表转树结构
* @param arr 数组
* @param id 条件id
* @param pid 父级id
* @param childName 子节点集合属性名
* @returns T[]
*/
function arrToTree(arr, id = 'id', pid = 'parentId', childName = 'children') {
const nodeMap = new Map();
const result = [];
for (const node of arr) {
node[childName] = node[childName] || [];
nodeMap.set(node[id], node);
}
for (const node of arr) {
const parent = nodeMap.get(node[pid]);
(parent ? parent[childName] : result).push(node);
}
return result;
}
/**
* 树结构转列表
* @param tree 树结构数据
* @param childName 子节点集合属性名
* @returns T[]
*/
function treeToArr(tree, childName = 'children') {
const result = [...tree];
for (let i = 0; i < result.length; i++) {
if (!result[i][childName]) {
continue;
}
result.splice(i + 1, 0, ...result[i][childName]);
}
return result;
}
/**
* 查找符合条件的单个节点
* @param tree 树结构数据
* @param func 条件
* @param childName 子节点集合属性名
* @returns T or null
*/
function findTreeNode(tree, func, childName = 'children') {
const list = [...tree];
for (const node of list) {
if (func(node)) {
return node;
}
node[childName] && list.push(...node[childName]);
}
return null;
}
/**
* 查找符合条件的所有节点
* @param tree 树结构数据
* @param func 条件
* @param childName 子节点集合属性名
* @returns T[]
*/
function findTreeNodeAll(tree, func, childName = 'children') {
const list = [...tree];
const result = [];
for (const node of list) {
func(node) && result.push(node);
node[childName] && list.push(...node[childName]);
}
return result;
}
/**
* 树结构遍历.
* 对于所有节点node调用callback(node),深度优先.
* @param tree 树结构数据
* @param func 条件
* @param childName 子节点集合属性名
*/
function forEachTreeNode(tree, func, childName = 'children') {
const list = [...tree];
for (let i = 0; i < list.length; i++) {
func(list[i]);
list[i][childName] && list.splice(i + 1, 0, ...list[i][childName]);
}
}
/**
* 删除符合条件的所有节点及其子节点.
* @param tree 树结构数据
* @param func 条件
* @param childName 子节点集合属性名
*/
function removeTreeNode(tree, func, childName = 'children') {
const list = [tree];
while (list.length) {
const nodeList = list.shift();
const delList = nodeList?.reduce((r, n, idx) => (func(n) && r.push(idx), r), []);
delList.reverse();
delList.forEach((idx) => nodeList?.splice(idx, 1));
const childrenList = nodeList?.map(n => n[childName]).filter(l => l && l.length) ?? [];
list.push(...childrenList);
}
}
/**
* 在指定oldNode前插入newNode.
* 如果树中没有oldNode,则不会改变原数组.
* @param tree 树结构数据
* @param newNode 新节点
* @param oldNode 指定节点
* @param childName 子节点集合属性名
*/
function insertTreeNodeBefore(tree, newNode, oldNode, childName = 'children') {
_insert(tree, oldNode, newNode, childName, 0);
}
/**
* 在指定oldNode后插入newNode.
* 如果树中没有oldNode,则不会改变原数组.
* @param tree 树结构数据
* @param oldNode 指定节点
* @param newNode 新节点
* @param childName 子节点集合属性名
*/
function insertTreeNodeAfter(tree, oldNode, newNode, childName = 'children') {
_insert(tree, oldNode, newNode, childName, 1);
}
function _insert(tree, node, targetNode, childName, after) {
function insert(list) {
const idx = list.indexOf(node);
idx < 0
? list.forEach(n => insert(n[childName] || []))
: list.splice(idx + after, 0, targetNode);
}
insert(tree);
}
/**
* 剔除字符串中所有空格及换行
*
* @param str 字符串
*/
function trimAll(str) {
return (str ?? '').replace(/[\s\n]+/g, '');
}
/**
*
* 字符串插入变量值
*
* interpolate('Hello {0}',['World']); // -> Hello World
*
* interpolate('Hello{0}',['World']); // -> HelloWorld
*
* @param text 文本
* @param params 参数
* @returns string
*/
function interpolate(text, params) {
return text
.replace(/(['"]?\{\s*(\d+)\s*\}['"]?)/g, (_, match, digit) => params[digit] ?? match)
.replace(/\s+/g, ' ');
}
/**
*
* 查找并替换一个字符串
*
* Example
*
* replaceAll('This is a test string', 'is', 'X') = 'ThX X a test string'
*
* @returns
*/
function replaceAll(str, search, replacement) {
const fix = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
return str.replace(new RegExp(fix, 'g'), replacement);
}
/**
*
* 截断字符串
*
* @param str 字符串
* @param maxLength 最大长度
* @returns string
*/
function truncateString(str, maxLength) {
if (!str || !str.length || str.length <= maxLength) {
return str;
}
return str.substring(0, maxLength);
}
/**
*
* 截断字符串带后缀
*
* @param str 字符串
* @param maxLength 最大长度
* @param postfix 后缀(默认...)
* @returns
*/
function truncateStringWithPostfix(str, maxLength, postfix) {
postfix = postfix || '...';
if (!str || !str.length || str.length <= maxLength) {
return str;
}
if (maxLength <= postfix.length) {
return postfix.substring(0, maxLength);
}
return str.substring(0, maxLength - postfix.length) + postfix;
}
/** 字符串翻转 */
function reverseStr(str) {
return str.split('').reverse().join('');
}
/**
* 生成uuid
* @returns string
*/
function uuid(a) {
return a
? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16)
: `${1e7}${-1e3}${-4e3}${-8e3}${-1e11}`.replace(/[018]/g, uuid);
}
/**
* 生成哈希值
* @returns number
*/
function generateHash(value) {
let hashed = 0;
let charCode;
for (let i = 0; i < value.length; i++) {
charCode = value.charCodeAt(i);
hashed = (hashed << 5) - hashed + charCode;
hashed |= 0;
}
return hashed;
}
/**
* 随机密码
* @param length 长度
* @returns string
*/
function generatePassword(length = 8) {
length = Math.min(Math.max(4, length), 128);
const lowers = 'abcdefghijklmnopqrstuvwxyz';
const uppers = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const numbers = '0123456789';
const specials = '!@#$%&*()_+{}<>?[]./';
const all = lowers + uppers + numbers + specials;
const getRandom = (chrSet) => chrSet[Math.floor(Math.random() * chrSet.length)];
const password = Array({ length });
password[0] = getRandom(lowers);
password[1] = getRandom(uppers);
password[2] = getRandom(numbers);
password[3] = getRandom(specials);
for (let i = 4; i < length; i++) {
password[i] = getRandom(all);
}
return password.sort(() => 0.5 - Math.random()).join('');
}
/**
*
* 复制/拷贝
*
* @returns
*/
function copy(source) {
return clone(source);
}
/**
* 根据 object对象的path路径获取值
*
* const obj = {a: {aa: {aaa: 2}}, b: 4};
*
* get(obj, 'a.aa.aaa'); // 2
* get(obj, ['a', 'aa', 'aaa']); // 2
*
* get(obj, 'b.bb.bbb'); // undefined
* get(obj, ['b', 'bb', 'bbb']); // undefined
*
* get(obj.a, 'aa.aaa'); // 2
* get(obj.a, ['aa', 'aaa']); // 2
*
* get(obj.b, 'bb.bbb'); // undefined
* get(obj.b, ['bb', 'bbb']); // undefined
*
* get(obj.b, 'bb.bbb', 42); // 42
* get(obj.b, ['bb', 'bbb'], 42); // 42
*
* get(null, 'a'); // undefined
* get(undefined, ['a']); // undefined
*
* get(null, 'a', 42); // 42
* get(undefined, ['a'], 42); // 42
*
* const obj = {a: {}};
* const sym = Symbol();
* obj.a[sym] = 4;
* get(obj.a, sym); // 4
* @param obj 对象
* @param path 路径
* @param defaultValue 默认值
* @returns SafeAny
*/
function deepGet(obj, path, defaultValue) {
if (!obj) {
return defaultValue;
}
let props, prop;
if (Array.isArray(path)) {
props = path.slice(0);
}
if (typeof path === 'string') {
props = path.split('.');
}
else if (typeof path === 'symbol') {
props = [path];
}
if (!Array.isArray(props)) {
throw new Error('props arg must be an array, a string or a symbol');
}
while (props.length) {
prop = props.shift();
if (!obj) {
return defaultValue;
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
obj = obj[prop];
if (obj === undefined) {
return defaultValue;
}
}
return obj;
}
/**
* 根据 object对象的path路径设置值
*
* const obj1 = {};
* set(obj1, 'a.aa.aaa', 4); // true
* set(obj1, 'a.aa.aaa', 4); // true
*
* const obj2 = {};
* set(obj2, ['a', 'aa', 'aaa'], 4); // true
* obj2; // {a: {aa: {aaa: 4}}}
*
* const obj3 = {a: {aa: {aaa: 2}}};
* set(obj3, 'a.aa.aaa', 3); // true
* obj3; // {a: {aa: {aaa: 3}}}
*
* const obj4 = {a: {aa: {aaa: 2}}};
* set(obj4, 'a.aa', {bbb: 7}); // false
*
* const obj5 = {a: {}};
* const sym = Symbol();
* set(obj5.a, sym, 7); // true
* obj5; // {a: {Symbol(): 7}}
*
* @param obj 对象
* @param path 路径
* @param value 值
* @returns boolean
*/
function deepSet(obj, path, value) {
let props;
if (Array.isArray(path)) {
props = path.slice(0);
}
if (typeof path === 'string') {
props = path.split('.');
}
else if (typeof path === 'symbol') {
props = [path];
}
if (!Array.isArray(props)) {
throw new Error('props arg must be an array, a string or a symbol');
}
const lastProp = props.pop();
if (!lastProp) {
return false;
}
prototypeCheck(lastProp);
let thisProp;
while ((thisProp = props.shift())) {
prototypeCheck(thisProp);
if (typeof obj[thisProp] === 'undefined') {
obj[thisProp] = {};
}
obj = obj[thisProp];
if (!obj || typeof obj !== 'object') {
return false;
}
}
obj[lastProp] = value;
return true;
}
function prototypeCheck(prop) {
if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
throw new Error('setting of prototype values not supported');
}
}
/**
*
* 深度合并
*
* @returns
*/
function deepMerge(target, source) {
if (isObjectAndNotArrayNotNode(target) && isObjectAndNotArrayNotNode(source)) {
return deepMergeRecursively(target, source);
}
else if (isNullOrUndefined(target) && isNullOrUndefined(source)) {
return {};
}
else {
return exists(source) ? source : target;
}
}
/**
*
* 递归深度合并
*
* @returns
*/
function deepMergeRecursively(target, source) {
const shouldNotRecurse = isNullOrUndefined(target) ||
isNullOrUndefined(source) || // at least one not defined
Array.isArray(target) ||
Array.isArray(source) || // at least one array
!isObject(target) ||
!isObject(source) || // at least one not an object
isNode(target) ||
isNode(source); // at least one node
/**
* if we will not recurse any further,
* we will prioritize source if it is a defined value.
*/
if (shouldNotRecurse) {
return exists(source) ? source : target;
}
const keysOfTarget = Object.keys(target);
const keysOfSource = Object.keys(source);
const uniqueKeys = new Set(keysOfTarget.concat(keysOfSource));
return [...uniqueKeys].reduce((retVal, key) => {
retVal[key] = deepMergeRecursively(target[key], source[key]);
return retVal;
}, {});
}
/**
*
* 映射枚举到选项
*
* @param _enum 枚举
* @returns []
*/
function mapEnumToOptions(_enum) {
const options = [];
for (const member in _enum)
if (!isNum(member)) {
options.push({
key: member,
value: _enum[member]
});
}
return options;
}
/**
* 浏览器内置uri解码`decodeURI()`函数的增强版,可以解码任何uri
*
* @param uri 地址
* @returns uri
*/
function superDecodeURI(uri) {
if (!uri) {
return uri;
}
return decodeURI(uri).replace(/%([0-9a-f]{2})/gi, (found, charCode) => String.fromCharCode(parseInt(charCode, 16)));
}
/**
*
* 将url中的参数解析为一个对象
*
* @param rawParam 格式为`var1=value1&var2=value2`
* @returns 返回类似`{var1: "value1", var2: "value2"}`的对象
*/
function parseUrlParam(rawParam) {
const result = {};
// eslint-disable-next-line no-extra-boolean-cast
if (!!rawParam) {
rawParam.split(/&/g).forEach(param => {
const parts = param.split(/=/);
result[superDecodeURI(parts[0])] = superDecodeURI(parts[1]);
});
}
return result;
}
/**
*
* 比较
*
* @description
* primitives: value1 === value
*
* functions: value1.toString == value2.toString
*
* arrays: if length, sequence and values of properties are identical
*
* objects: if length, names and values of properties are identical
*
* @example
* compare([[1, [2, 3]], [[1, [2, 3]]);=> true
*
* compare([[1, [2, 3], 4], [[1, [2, 3]]);=> false
*
* compare({a: 2, b: 3}, {a: 2, b: 3});=> true
*
* compare({a: 2, b: 3}, {b: 3, a: 2});=> true
*
* compare({a: 2, b: 3, c: 4}, {a: 2, b: 3});=> false
*
* compare({a: 2, b: 3}, {a: 2, b: 3, c: 4});=> false
*
* compare([[1, [2, {a: 4}], 4], [[1, [2, {a: 4}]]);=> true
*
* @returns boolean
*/
function compare(value1, value2) {
if (value1 === value2) {
return true;
}
/* eslint-disable no-self-compare */
// if both values are NaNs return true
if (value1 !== value1 && value2 !== value2) {
return true;
}
if ({}.toString.call(value1) !== {}.toString.call(value2)) {
return false;
}
if (value1 !== Object(value1)) {
// non equal primitives
return false;
}
if (!value1) {
return false;
}
if (Array.isArray(value1)) {
return compareArrays(value1, value2);
}
if ({}.toString.call(value1) === '[object Set]') {
return compareArrays(Array.from(value1), Array.from(value2));
}
if ({}.toString.call(value1) === '[object Object]') {
return compareObjects(value1, value2);
}
else {
return compareNativeSubtypes(value1, value2);
}
}
function compareNativeSubtypes(value1, value2) {
// e.g. Function, RegExp, Date
return value1.toString() === value2.toString();
}
/**
*
* 比较数组
*
* @returns boolean
*/
function compareArrays(value1, value2) {
const len = value1.length;
if (len !== value2.length) {
return false;
}
let alike = true;
for (let i = 0; i < len; i++) {
if (!compare(value1[i], value2[i])) {
alike = false;
break;
}
}
return alike;
}
/**
*
* 比较Obj
*
* @returns boolean
*/
function compareObjects(value1, value2) {
const keys1 = Object.keys(value1).sort();
const keys2 = Object.keys(value2).sort();
const len = keys1.length;
if (len !== keys2.length) {
return false;
}
for (let i = 0; i < len; i++) {
const key1 = keys1[i];
const key2 = keys2[i];
if (!(key1 === key2 && compare(value1[key1], value2[key2]))) {
return false;
}
}
return true;
}
/**
* Generated bundle index. Do not edit.
*/
export { arrToJson, arrToJsonArr, arrToTree, checkBox, compare, compareArrays, compareObjects, copy, deepGet, deepMerge, deepSet, exists, findTreeNode, findTreeNodeAll, forEachTreeNode, generateHash, generatePassword, getBrowserCultureLang, getBrowserLang, insertTreeNodeAfter, insertTreeNodeBefore, interpolate, is, isDecimal, isEmail, isFunction, isIdCard, isInt, isIp, isJson, isMobile, isNode, isNonEmptyString, isNull, isNullOrUndefined, isNum, isObject, isObjectAndNotArray, isObjectAndNotArrayNotNode, isOdd, isString, isUndefined, isUndefinedOrEmptyString, isUrl, jsonToArr, mapEnumToOptions, noop, parseUrlParam, removeTreeNode, replaceAll, reverseStr, superDecodeURI, toBoolean, toHash, toLength, toNumber, toString, treeToArr, trimAll, truncateString, truncateStringWithPostfix, uuid };
//# sourceMappingURL=pkt-utils.mjs.map