UNPKG

@fe6/shared

Version:

水滴共享函数集

1,538 lines (1,524 loc) 36 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /* eslint-disable no-useless-escape */ // 按344位数切割手机号,用于手机脱敏等 const rePhone344 = /(\d{3})\d{4}(\d{4})/g; // 手机号正则 const rePhone = /^1[3456789]\d{9}$/; // 区号+座机正则 const reLandlineAll = /^(0[0-9]{2,3}\-)([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$/; // 座机的区号正则 const reLandlineAreaCode = /^(0[0-9]{2,3})?$/; // 座机电话正则 const reLandlineTel = /^([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$/; // 金额格式化正则,匹配: 12,222,222.11 const reMoneyPrettify = /\d{1,3}(?=(\d{3})+(\.\d*)?$)/g; // 驼峰转字母横线的正则 const reHyphenate = /\B([A-Z])/g; // 只能输入数字和英文 const reOnlyEnOrNum = /^[0-9A-Za-z]+$/g; // 只能中文 const reOnlyCn = /^[\u4e00-\u9fa5]+$/g; // 正数 const rePlusNumber = /^\d+(\.\d+)?$/; // Email const reEmail = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/; // 地址 的正则 // v 0.5.0 新增 const reUrl = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; // 一段字符串里面有 地址 的正则 // v 0.6.0 新增 const reUrlInString = /(((https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; /** * 获取 字母横线( 或其他 )转驼峰的正则 * * * @since 0.1.0 * @category Reg * @param {string} [separator] 连接符,默认是 - * @returns {RegExp} 返回正则 * @example * * reCamelize() * // => /-(\w)/g; * * reCamelize('+') * // => /+(\w)/g * */ const reCamelize = (separator = '-') => { const newSeparator = typeof separator !== 'string' || separator === '+' || separator === '*' ? '-' : separator; return new RegExp(`${newSeparator}(\\w)`, 'g'); }; /** * 对象转字符串方法 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {function} 返回方法 * @example * * objectToString.call('value') * // => [object String] * * objectToString.call(123) * // => [object Number] */ const objectToString = Object.prototype.toString; /** * 获取类型通用方法 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {string} 字符串, 如 [object Number] * @example * * toTypeString('value') * // => [object String] * * toTypeString(123) * // => [object Number] */ const toTypeString = (value) => objectToString.call(value); /** * 获取类型简便方法 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {string} 字符串, 如 Number * @example * * like('value') * // => String * * like(123) * // => Number */ const like = (val = undefined) => toTypeString(val).replace(/(\[object )(\w*)(\])/g, (a, p1, type) => type); /** * 是否是 Arguments * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isArguments('value') * // => false * * isArguments(123) * // => true */ const isArguments = (val = undefined) => like(val) === "Arguments" /* ARGUMENTS */; /** * 是否是数字 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isNumber('value') * // => false * * isNumber(123) * // => true */ const isNumber = (val = undefined) => like(val) === "Number" /* NUMBER */; /** * 是否是字符串 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isString('value') * // => true * * isString(123) * // => false */ const isString = (val = undefined) => like(val) === "String" /* STRING */; /** * 是否是 symbol * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isSymbol(Symbol()) * // => true * * isSymbol(123) * // => false */ const isSymbol = (val = undefined) => like(val) === "Symbol" /* SYMBOL */; /** * 是否是布尔值 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isBoolean(true) * // => true * * isBoolean(123) * // => false */ const isBoolean = (val = undefined) => like(val) === "Boolean" /* BOOLEAN */; /** * 是否是函数 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isSymbol(Function) * // => true * * isSymbol(123) * // => false */ const isFunction = (val = undefined) => like(val) === "Function" /* FUNCTION */; /** * 是否是 undefined * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isUndefined(undefined) * // => true * * isUndefined(123) * // => false */ const isUndefined = (val = undefined) => like(val) === "Undefined" /* UNDEFINED */; /** * 是否是 null * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isNull(null) * // => true * * isNull(void 0) * // => false */ const isNull = (val = undefined) => like(val) === "Null" /* NULL */; /** * 是否是数组 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isArray([1]) * // => true * * isArray(123) * // => false */ const isArray = (val = undefined) => like(val) === "Array" /* ARRAY */; /** * 是否是普通对象 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isPlainObject({}) * // => true * * isPlainObject(123) * // => false */ const isPlainObject = (val = undefined) => like(val) === "Object" /* OBJECT */; /** * 是否是 promise * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isPromise(new Promise(function(a) {a()});) * // => true * * isPromise(123) * // => false */ const isPromise = (val = undefined) => like(val) === "Promise" /* PROMISE */; /** * 是否是 Set 对象 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isSet(new Set()) * // => true * * isSet(123) * // => false */ const isSet = (val = undefined) => like(val) === "Set" /* SET */; /** * 是否是 WeakSet 对象 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isWeakSet(new WeakSet()) * // => true * * isWeakSet(123) * // => false */ const isWeakSet = (val = undefined) => like(val) === "WeakSet" /* WEAKSET */; /** * 是否是 Map 对象 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isMap(new Map()) * // => true * * isMap(123) * // => false */ const isMap = (val = undefined) => like(val) === "Map" /* MAP */; /** * 是否是 Date 对象 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isDate(new Date()) * // => true * * isDate(123) * // => false */ const isDate = (val = undefined) => like(val) === "Date" /* DATE */; /** * 检查 'val' 是否可能是原型对象。 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isPrototype({a: 'as'}) * // => true * * isPrototype(12) * // => false */ const isPrototype = (val = undefined) => { const functionVal = val; const Ctor = functionVal && functionVal.constructor; const objectProto = Object.prototype; const proto = (isFunction(Ctor) && Ctor.prototype) || objectProto; return val === proto; }; /** * 是否是 NaN * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isNaN('f100') * // => true * * isNaN(123) * // => false */ const isNaN = (val = undefined) => { if (isSymbol(val)) { return true; } const num = Number(val); /* eslint-disable no-self-compare */ return num !== num; }; /** * 是否是空对象,集合,映射或者set * 判断的依据是除非是有枚举属性的对象,length 大于 0 的 arguments object , array , string 。 * * * @since 0.1.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isEmpty(null); * // => true * * isEmpty(true); * // => true * * isEmpty(1); * // => true * * isEmpty([1, 2, 3]); * // => false * * isEmpty({ 'a': 1 }); * // => false */ const isEmpty = (val = undefined) => { if (isArray(val)) { const arrayVal = val; return !arrayVal.length; } if (isString(val)) { const arrayVal = val; return !arrayVal.length; } if (isMap(val) || isSet(val)) { const arrayVal = val; return !arrayVal.size; } const anyVal = val; const objectVal = val; if (isPrototype(val)) { return !Object.keys(objectVal).length; } if (isPlainObject(anyVal) || isArguments(anyVal)) { const valKeys = Object.keys(anyVal); if (valKeys.length > 0) { return false; } } return true; }; /** * 是否是地址 * * * * @since 0.5.0 * @category Lang * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isUrl('http://www.water.com'); * // => true * * isUrl('https://www.water.com'); * // => true * * isUrl('https://www.water.com?good=true'); * // => true * * isUrl(null); * // => false * * isUrl(false); * // => false * * isUrl(1); * // => false * * isUrl([1, 2, 3]); * // => false * * isUrl({ 'a': 1 }); * // => false */ function isUrl(path) { if (!isString(path)) { return false; } const pathString = path; return reUrl.test(pathString); } const { hasOwnProperty } = Object.prototype; /** * 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。 * * * @since 0.1.0 * @category Object * @param {*} item 目标对象 * @param {string} attr 要检测的属性 * @returns {boolean} 用来判断某个对象是否含有指定的属性的布尔值 * @example * * hasOwn({ name: 'lee' }, 'name') * // => true * * hasOwn({ name: 'lee' }, 'age') * // => false */ const hasOwn = (item, attr) => { if (!isPlainObject(item) || !attr) { return false; } return hasOwnProperty.call(item, attr); }; const { keys } = Object; /** * 深度合并 * * * @since 0.7.0 * @category Object * @param {*} src 元对象 * @param {*} target 目标对象 * @returns {T} 返回新对象 * @example * * deepMerge({ name: 'lee' }, { name: 'foo' }) * // => { name: 'foo' } */ function deepMerge(src = {}, target = {}) { if (!isPlainObject(src) || !isPlainObject(target)) { return {}; } const newObj = { ...target }; keys(src).forEach((attr) => { if (isPlainObject(src[attr])) { newObj[attr] = deepMerge(src[attr], target[attr]); } else if (isArray(target[attr])) { newObj[attr] = target[attr].slice(); } else { newObj[attr] = target[attr]; } }); return newObj; } /** * 克隆 * * * @format * @since 0.1.0 * @category Clone * @param {*} val 要复制的值。 * @returns {any} 返回结果 * @example * * clone([1,2,3,4]) * // [1,2,3,4] * * clone({a: 1, b: 2}) * // {a: 1, b: 2} * * clone(111) * // 111 */ const clone = (val) => { if (isArray(val) && !isEmpty(val)) { return val.map(clone); } if (isPlainObject(val) && !isEmpty(val)) { const res = {}; keys(val).forEach((valKey) => { res[valKey] = clone(val[valKey]); }); return res; } return val; }; /** * 是否是浏览器端 * * * @format * @since 0.1.0 * @category Device * @returns {boolean} 返回结果 * @example * * isClient() * // true */ const isClient = () => !!(typeof window !== 'undefined' && window.document && window.document.createElement); /** * 文件字节大小的转换 * * * @since 0.1.0 * @category Format * @param {number} num 要转换的大小 * @returns {function} 返回带单位的大小 * @example * * fileSize(1111) * // => {"size": 1.08, "unit": "KB"} * * fileSize(0) * // => {size: 0, unit: 'bytes'} */ const fileSize = (num) => { if (isUndefined(num)) { return { size: 0, unit: '', }; } let unit = 'bytes'; let size = num || 0; let p = 0; if (size > 0 && size < 1024) { p = 0; return { size, unit, }; } if (size >= 1024 && size < 1024 ** 2) { p = 1; unit = "KB" /* KB */; } if (size >= 1024 ** 2 && size < 1024 ** 3) { p = 2; unit = "MB" /* MB */; } if (size >= 1024 ** 3 && size < 1024 ** 4) { p = 3; unit = "GB" /* GB */; } if (size >= 1024 ** 4 && size < 1024 ** 5) { p = 3; unit = "TB" /* TB */; } size /= 1024 ** p; return { size: Number(size.toFixed(2)), unit, }; }; /** * 手机号脱敏 * * * @since 0.1.0 * @category Format * @param {string|number} phone 手机号 * @returns {string} 返回脱敏之后的手机号 * @example * * phone(13810902078) * // => '138***2078' * * phone('13810902078') * // => '138***2078' * * phone('aaa') * // => '' */ const phone = (codePhone = '') => { if (!isString(codePhone) && !isNumber(codePhone)) { return ''; } const tel = String(codePhone); if (!rePhone.test(tel)) { return ''; } return tel.replace(rePhone344, '$1****$2'); }; /** * 金额格式化 * 必须得符合金钱的验证 * * @since 0.1.0 * @category Format * @param {string|number} money 金额 * @param {boolean} [reverse] 是否反转, 如果存在并且为 true ',' 取消 ,的添加,否则是添加 ',' * @returns {string} 返回格式化之后的金额 * @example * * money(12222.22) * // => '12,222.22' * * money('12222.22') * // => '12,222.22' * * money('aaa') * // => '' * * money('12,222.22', true) * // => '12222.22' * * money('12,222.22') * // => '12222.22' */ const money = (coin = '', reverse) => { if (!isString(coin) && !isNumber(coin)) { return ''; } const cash = String(coin); const cashList = cash.split('.'); const hasFloat = cashList.length > 1; const cashNeed = cashList[0]; let needed = ''; const reReverse = /,/g; const hasComma = reReverse.test(cashNeed); if (!hasComma && !reMoneyPrettify.test(cashNeed)) { return ''; } const isReverse = reverse || hasComma; needed = isReverse ? cashNeed.replace(reReverse, '') : `${cashNeed}`.replace(reMoneyPrettify, '$&,'); return hasFloat ? `${needed}.${cashList[1]}` : needed; }; /** * 小写连接符转换成驼峰 * * * @since 0.1.0 * @category Format * @param {string} word 处理的单词字符串 * @param {string} [separator] 连接符,默认是 - * @returns {string} 返回格式化之后的单词 * @example * * camelize('water-isVery-good') * // => 'waterIsVeryGood' * * camelize('water+isVery+good', '+') * // => 'waterIsVeryGood' * * camelize('水滴') * // => '' * * camelize('12222.22') * // => '' * * camelize('aaa') * // => '' */ const camelize = (word = '', separator = '-') => { if (!isString(word)) { return ''; } const newWord = word; if (separator === '+' || separator === '*' || !reCamelize(separator).test(newWord)) { return ''; } return newWord.replace(reCamelize(separator), (_, item) => item.toUpperCase()); }; /** * 驼峰转换成小写连接符 * * * @since 0.1.0 * @category Format * @param {string} word 处理的单词字符串 * @param {string} [separator] 连接符,默认是 - * @returns {string} 返回格式化之后的单词 * @example * * hyphenate('111F') * // => '100-f' * * hyphenate('WaterIsVeryGood', '+') * // => 'water+is+very+good' * * hyphenate('水滴') * // => '' * * hyphenate('12222.22') * // => '' * * hyphenate('aaa') * // => '' */ const hyphenate = (word = '', separator = '-') => { if (!isString(word)) { return ''; } const newWord = word; if (!reHyphenate.test(newWord)) { return ''; } return newWord.replace(reHyphenate, `${separator}$1`).toLowerCase(); }; /** * 首字母大写 * * * @since 0.1.0 * @category Format * @param {string} word 处理的单词字符串 * @returns {string} 返回格式化之后的单词 * @example * * firstCapitalize(12222.22) * // => '' * * firstCapitalize('12222.22') * // => '' * * firstCapitalize('aaa') * // => 'Aaa' * * firstCapitalize('水滴aaa') * // => '水滴aaa' * * firstCapitalize('aaa水滴') * // => 'Aaa水滴' */ const firstCapitalize = (word = '') => { if (!isString(word)) { return ''; } const newWord = word; const firstWord = newWord.charAt(0); if (!/^[A-Za-z]/.test(firstWord)) { return ''; } return firstWord.toUpperCase() + newWord.slice(1); }; /** * 对象转化为get请求的链接参数 * * * @since 0.3.0 * @category Object * @param {*} item 目标对象 * @param {string} [baseUrl] 基本链接 * @returns {string} 格式化好的字符串 * @example * * objectToQuery({ name: 'www.baidu.com' }, 'www.water.com') * // => www.baidu.com?name=lee * * objectToQuery({a: '3', b: '4'}) * // => a=3&b=4 */ const objectToQuery = (item, baseUrl) => { let parameters = ''; if (isPlainObject(item)) { const plainObj = item; parameters = keys(plainObj).reduce((acc, attr) => { return `${attr}=${encodeURIComponent(plainObj[attr])}&${acc}`; }, ''); } parameters = parameters.replace(/&$/, ''); if (isString(baseUrl)) { const baseUrlStr = baseUrl; return /\?$/.test(baseUrlStr) ? baseUrlStr + parameters : baseUrlStr.replace(/\/?$/, '?') + parameters; } return parameters; }; /** * 是否是负数 * * * @since 0.1.0 * @category Number * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isMinus(-100) * // => true * * isMinus(-100.11) * // => true * * isMinus(123) * // => false */ const isMinus = (val = undefined) => { if (isSymbol(val) || isNaN(Number(val))) { return false; } const str = String(val); return str[0] === '-'; }; /** * 是否是整数 * * * @since 0.1.0 * @category Number * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isInteger(-100) * // => true * * isInteger(100) * // => true * * isInteger(12.3) * // => false * * isInteger(-12.3) * // => false */ const isInteger = (val = undefined) => isNumber(val) && Number.isFinite(val) && Math.floor(val) === val; /** * 是否是正整数 * * * @since 0.1.0 * @category Number * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isPlusInteger(100) * // => true * * isPlusInteger(-12) * // => false */ const isPlusInteger = (val = undefined) => isInteger(val) && !isMinus(val); /** * 是否是小数 * * * @since 0.1.0 * @category Number * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isFloat(100) * // => true * * isFloat(-12) * // => false */ const isFloat = (val = undefined) => !isUndefined(val) && !isNaN(val) && isNumber(val) && !isInteger(val); /** * 是否是负整数 * * * @since 0.1.0 * @category Number * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * isMinusInteger(-100) * // => true * * isMinusInteger(12) * // => false */ const isMinusInteger = (val = undefined) => isInteger(val) && isMinus(val); /** * 获取一段区间内的随机数 * * * @since 0.1.0 * @category Number * @param {number} minValue 最小区间 * @param {number} minValue 最大区间 * @param {boolean} isFloat 是否是小数 * @returns {number} 返回在最大最小区间内包括最大最小区间的整数 * @example * * randomNumber(-100, 1) * // 生成 -100 到 1 之间的整数 * // => 1 * * randomNumber(12, 22) * // 生成 12 到 22 之间的整数 * // => 12 * * randomNumber(1, 3) * // 生成 1 到 3 之间的整数 * // => 2 * * randomNumber(1.1, 3.2) * // 生成 1.1 到 3.2 之间的小数 * // => 2.2 * * randomNumber(1, 3.2) * // 生成 1 到 3.2 之间的小数 * // => 2.2 * * randomNumber(1.1, 3) * // 生成 1 到 3 之间的小数 * // => 2.2 * * randomNumber(1, 3, true) * // 生成 1 到 3 之间的小数 * // => 2.2 */ const randomNumber = (minValue, maxValue, isFloating) => { if (isNaN(minValue) || !isNumber(minValue) || isNaN(maxValue) || !isNumber(maxValue)) { return 0; } const minNum = minValue; const maxNum = maxValue; // 如果是小数 if (isFloating || isFloat(minNum) || isFloat(maxNum)) { const rand = Math.random(); const randLength = `${rand}`.length - 1; return Math.min(minNum + rand * (maxNum - minNum + parseFloat(`1e-${randLength}`)), maxNum); } // 取值范围总数 const choices = maxNum - minNum + 1; return Math.floor(Math.random() * choices + minNum); }; /** * 是否是负整数 * * * @since 0.1.0 * @category Number * @param {*} val 要检查的值。 * @returns {boolean} 如果是返回 true ,否则返回 false * @example * * inRange(3, 2, 4) * // => true * * inRange(4, 8) * // => true * * inRange(4, 2) * // => false * * inRange(2, 2) * // => false * * inRange(1.2, 2) * // => true * * inRange(5.2, 4) * // => false * * inRange(-3, -2, -6) * // => true */ const inRange = (val = undefined, start = 0, end) => { if (!isNumber(val) || isSymbol(start) || !isNumber(start)) { return false; } let startNum = start; const valNum = val; let endNum = startNum; if (isUndefined(end)) { startNum = 0; } if (!isUndefined(end) && !isNumber(end)) { return false; } if (!isUndefined(end) && isNumber(end)) { endNum = end; } return (valNum >= Math.min(startNum, endNum) && valNum < Math.max(startNum, endNum)); }; /** * 计算的基础 * * * @since 0.1.0 * @category Number * @param {function} operator 执行操作的方法。 * @param {number} [defaultValue] 参数默认值 * @returns {Function} 返回新的数学运算函数。 * @example * * count(augend, addend) => augend + addend, 0)(1, 2) * // => 3 * * count(augend, addend) => augend + addend, 0)(1) * // => 2 * * count(augend, addend) => augend + addend, 7)() * // => 7 */ const count = (operator, defaultValue = 0) => (oneVal, twoVal) => { if (isUndefined(oneVal) && isUndefined(twoVal)) { return defaultValue; } let oneNewVal = oneVal; let twoNewVal = twoVal; if (isSymbol(oneNewVal) && isSymbol(twoNewVal)) { return defaultValue; } if (isSymbol(oneNewVal) && !isSymbol(twoNewVal)) { oneNewVal = twoNewVal; } if (!isSymbol(oneNewVal) && isSymbol(twoNewVal)) { twoNewVal = oneNewVal; } let oneNum = Number(oneNewVal); let twoNum = isUndefined(twoNewVal) ? oneNum : Number(twoNewVal); if (isNaN(oneNum) && isNaN(twoNum)) { return defaultValue; } if (isNaN(oneNum) && !isNaN(twoNum)) { oneNum = twoNum; } if (!isNaN(oneNum) && isNaN(twoNum)) { twoNum = oneNum; } return operator(oneNum, twoNum); }; /** * 将两个数字相加 * * @since 0.1.0 * @category Math * @param {unknown} oneValue 运算中的第一个数字 * @param {unknown} twoValue 运算中的第二个数字 * @returns {number} 返回总和 * @example * * add() * // => 0 * * add(1, 2) * // => 3 * * add(1) * // => 2 */ const add = count((oneValue, twoValue) => { const oneNum = oneValue; const twoNum = twoValue; return oneNum + twoNum; }, 0); /** * 将两个数字相减 * * @since 0.1.0 * @category Math * @param {unknown} oneValue 运算中的第一个数字 * @param {unknown} twoValue 运算中的第二个数字 * @returns {number} 返回总和 * @example * * subtract() * // => 0 * * subtract(6, 4) * // => 2 * * subtract(1, 2) * // => -1 * * subtract(1) * // => 0 */ const subtract = count((oneValue, twoValue) => { const oneNum = oneValue; const twoNum = twoValue; return oneNum - twoNum; }, 0); /** * 将两个数字相乘 * * @since 0.1.0 * @category Math * @param {unknown} oneValue 运算中的第一个数字 * @param {unknown} twoValue 运算中的第二个数字 * @returns {number} 返回总和 * @example * * multiply() * // => 1 * * multiply(1, 2) * // => 2 * * multiply(3) * // => 9 */ const multiply = count((oneValue, twoValue) => { const oneNum = oneValue; const twoNum = twoValue; return oneNum * twoNum; }, 1); /** * 将两个数字相除 * * @since 0.1.0 * @category Math * @param {unknown} oneValue 运算中的第一个数字 * @param {unknown} twoValue 运算中的第二个数字 * @returns {number} 返回总和 * @example * * divide() * // => 1 * * divide(1, 2) * // => 0.5 * * divide(3) * // => 1 */ const divide = count((oneValue, twoValue) => { const oneNum = oneValue; const twoNum = twoValue; return oneNum / twoNum; }, 1); const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7; /** * 创建 Storage * * * @since 0.4.0 * @category Storage * @param {string} [prefixKey] 前缀 * @param {string} [storage] 指定 storage 类型 * @returns {WebStorage} 返回 WebStorage 对象 * @example * * createStorage('prefixKey') * * reCamelize('prefixKey', sessionStorage) * // => /+(\w)/g * */ const createStorage = ({ prefixKey, storage, } = {}) => { /** *Cache class *Construction parameters can be passed into sessionStorage, localStorage, * @class Cache * @example */ const WebStorage = class WebStorage { /** * * @param {*} storage */ constructor() { this.storage = storage || localStorage; this.prefixKey = prefixKey || ''; } /** * 获取 Storage 存储的 key * * * @since 0.4.0 * @category Storage * @param {string} [key] key * @returns {string} 返回 存储的 key * @example * * getKey('prefixKey') * */ getKey(key) { return isString(key) ? `${this.prefixKey}${key}`.toUpperCase() : ''; } /** * 设置 Storage * * * @since 0.4.0 * @category Storage * @param {string} key key * @param {string} value value * @param {number} [expire] 过期时间,单位 秒 s * @returns {void} void * @example * * set('prefixKey', 123) * set('prefixKey', 123, 1000) * */ set(key, value, exp) { if (isString(key) && key !== '') { const expNumber = isSymbol(exp) ? 0 : Number(exp); const expire = isNumber(exp) && !isNaN(expNumber) && expNumber > 0 ? new Date().getTime() + Number(exp) * 1000 : null; const stringData = JSON.stringify({ value, expire, }); const stringifyValue = stringData; this.storage.setItem(this.getKey(key), stringifyValue); } } /** * 获取 Storage * 过期了自动删除 * * @since 0.4.0 * @category Storage * @param {string} key key * @param {string} def 不存在 key 的默认返回 * @returns {void} void * @example * * get('prefixKey', 123) * get('prefixKey', 123) * */ get(key, def = '') { const item = this.storage.getItem(this.getKey(key)); if (item) { const decItem = item; const data = JSON.parse(decItem); const { value, expire } = data; if (expire === null || expire >= new Date().getTime()) { return value; } this.remove(this.getKey(key)); return ''; } return def; } /** * 删除 key 的 Storage * * @since 0.4.0 * @category Storage * @param {string} key key * @param {string} def 不存在 key 的默认返回 * @returns {void} void * @example * * remove('prefixKey') * */ remove(key) { this.storage.removeItem(this.getKey(key)); } /** * Delete all caches of this instance */ /** * 删除 所有 的 Storage * * @since 0.4.0 * @category Storage * @returns {void} void * @example * * clear() * */ clear() { this.storage.clear(); } }; return new WebStorage(); }; /** * 4位随机数 * @static * @since 0.1.0 * @returns {string} 随机数 * @example * * var shallow = _.guidS4(objects); * console.log(shallow); // 359b */ const guidS4 = () => Math.ceil((1 + Math.random()) * 0x10000) .toString(16) .substring(1); /** * 生成32位码 * @static * @since 0.1.0 * @returns {string} 随机数 * @example * * var shallow = _.guid(); * console.log(shallow); // 359b53bab8ff1b0b1f7f9a32ac20c2aa */ const uuid = () => `${guidS4()}${guidS4()}${guidS4()}${guidS4()}${guidS4()}${guidS4()}${guidS4()}${guidS4()}`; /** * 获取 url 问号后面的某一个值 * @static * @since 1.0.7 * @returns {string} Returns '' * @example * * url http://underline.com?underline=lee * var shallow = _.searchUrl('aaa'); * console.log(shallow); // lee * * url http://underline.com?underline=lee * var shallow = _.searchUrl('em'); * console.log(shallow); // '' * * url http://underline.com * var shallow = _.searchUrl('em'); * console.log(shallow); // '' */ function searchUrl(name) { const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i'); const url = window.location.href.split('?'); if (!url[1]) { return ''; } const matchSearch = url[1].match(reg); return matchSearch ? matchSearch[2] : ''; } /** * 获取中英文字符串,中文占两个长度 * * @since 0.9.0 * @category Math * @param {unknown} oneValue 运算中的第一个数字 * @param {unknown} twoValue 运算中的第二个数字 * @returns {number} 返回总和 * @example * * getStrLength() * // => 0 * * getStrLength('水滴', '22') * // => 4 * * getStrLength('water') * // => 5 */ const getStrLength = (str, replaceValue = 'ww') => { if (!isString(str)) { return 0; } /* eslint-disable no-control-regex */ return String(str).replace(/[^\x00-\xff]/g, replaceValue).length; }; exports.DEFAULT_CACHE_TIME = DEFAULT_CACHE_TIME; exports.add = add; exports.camelize = camelize; exports.clone = clone; exports.count = count; exports.createStorage = createStorage; exports.deepMerge = deepMerge; exports.divide = divide; exports.fileSize = fileSize; exports.firstCapitalize = firstCapitalize; exports.getStrLength = getStrLength; exports.hasOwn = hasOwn; exports.hyphenate = hyphenate; exports.inRange = inRange; exports.isArguments = isArguments; exports.isArray = isArray; exports.isBoolean = isBoolean; exports.isClient = isClient; exports.isDate = isDate; exports.isEmpty = isEmpty; exports.isFloat = isFloat; exports.isFunction = isFunction; exports.isInteger = isInteger; exports.isMap = isMap; exports.isMinus = isMinus; exports.isMinusInteger = isMinusInteger; exports.isNaN = isNaN; exports.isNull = isNull; exports.isNumber = isNumber; exports.isPlainObject = isPlainObject; exports.isPlusInteger = isPlusInteger; exports.isPromise = isPromise; exports.isPrototype = isPrototype; exports.isSet = isSet; exports.isString = isString; exports.isSymbol = isSymbol; exports.isUndefined = isUndefined; exports.isUrl = isUrl; exports.isWeakSet = isWeakSet; exports.keys = keys; exports.like = like; exports.money = money; exports.multiply = multiply; exports.objectToQuery = objectToQuery; exports.objectToString = objectToString; exports.phone = phone; exports.randomNumber = randomNumber; exports.reCamelize = reCamelize; exports.reEmail = reEmail; exports.reHyphenate = reHyphenate; exports.reLandlineAll = reLandlineAll; exports.reLandlineAreaCode = reLandlineAreaCode; exports.reLandlineTel = reLandlineTel; exports.reMoneyPrettify = reMoneyPrettify; exports.reOnlyCn = reOnlyCn; exports.reOnlyEnOrNum = reOnlyEnOrNum; exports.rePhone = rePhone; exports.rePhone344 = rePhone344; exports.rePlusNumber = rePlusNumber; exports.reUrl = reUrl; exports.reUrlInString = reUrlInString; exports.searchUrl = searchUrl; exports.subtract = subtract; exports.toTypeString = toTypeString; exports.uuid = uuid;