关于前端常用的部分公共方法

1.判断两数组字符串是否相同(用于按钮权限验证),数组字符串中存在相同时会自动去重(按钮权限标识不会重复)

使用Set数据结构可以更高效地判断数组内容是否相同:

/**
 * 判断两数组内容是否相同(自动去重)
 * @param newArr 新数据 
 * @param oldArr 源数据
 * @returns 两数组内容相同返回true
 */
export function judementSameArr(
    newArr: unknown[] | string[],
    oldArr: string[]
): boolean {
    const set1 = new Set(newArr);
    const set2 = new Set(oldArr);
    
    if (set1.size !== set2.size) return false;
    
    for (const item of set1) {
        if (!set2.has(item)) return false;
    }
    
    return true;
}

性能说明

  • 时间复杂度降为O(n)
  • 正确性更高
  • 代码更简洁易读
  • 保留了自动去重的特性

使用示例

const arr1 = ['a', 'b', 'c'];
const arr2 = ['c', 'b', 'a'];
console.log(judementSameArr(arr1, arr2)); // true

const arr3 = ['a', 'b', 'b'];
const arr4 = ['a', 'b'];
console.log(judementSameArr(arr3, arr4)); // true

2. 判断两个对象是否相同,全面的类型检查和递归处理:

/**
 * 深度比较两个对象的值是否相等
 * @param a 要比较的第一个对象
 * @param b 要比较的第二个对象
 * @returns 如果对象值完全相同返回true,否则返回false
 */
export function deepEqual<T>(a: T, b: T): boolean {
  if (a === b) return true;
  if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;

  const keysA = Object.keys(a) as Array<keyof T>;
  const keysB = Object.keys(b) as Array<keyof T>;

  if (keysA.length !== keysB.length) return false;

  for (const key of keysA) {
    if (!b.hasOwnProperty(key)) return false;
    
    const valA = a[key];
    const valB = b[key];
    const areObjects = isObject(valA) && isObject(valB);

    if ((areObjects && !deepEqual(valA, valB)) || (!areObjects && valA !== valB)) {
      return false;
    }
  }

  return true;
}

function isObject(obj: unknown): obj is Record<string, unknown> {
  return obj !== null && typeof obj === 'object';
}

要点:

  • 添加了类型谓词函数确保对象类型检查
  • 使用更精确的keyof类型标注
  • 优化了基本类型比较逻辑
  • 减少了不必要的变量声明
  • 添加了更详细的类型注释

测试用例示例:

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
const obj3 = { a: 1, b: { c: 3 } };

console.log(deepEqual(obj1, obj2)); // true
console.log(deepEqual(obj1, obj3)); // false
console.log(deepEqual(null, null)); // true
console.log(deepEqual(undefined, undefined)); // true

3.  数组、数组对象去重;

代码功能说明

该函数用于对数组或数组对象进行去重操作。对于普通数组直接使用Set去重,对于对象数组可以根据指定属性值去重。

参数说明

  • arr: 需要去重的数组或对象数组
  • attr(可选): 对象数组中用于判断重复的属性名

使用示例

// 普通数组去重
const simpleArr = [1, 2, 2, 3];
const uniqueSimple = removeDuplicate(simpleArr); // [1, 2, 3]

// 对象数组去重
const objArr = [
  {id: 1, name: 'A'},
  {id: 2, name: 'B'}, 
  {id: 1, name: 'C'}
];
const uniqueObj = removeDuplicate(objArr, 'id'); 
// 结果:[{id:1,name:'A'},{id:2,name:'B'}]

代码优化

export function removeDuplicate<T>(arr: T[], attr?: keyof T): T[] {
  if (!arr?.length) return arr;
  
  if (attr) {
    const seen = new Set();
    return arr.filter(item => {
      const key = item[attr];
      return seen.has(key) ? false : (seen.add(key), true);
    });
  }
  
  return [...new Set(arr)];
}

优化点:

  1. 添加泛型支持增强类型推断
  2. 使用更现代的Setfilter方法
  3. 简化条件判断逻辑
  4. 改进变量命名 

该函数适用于大多数常见的去重场景,特别是处理对象数组时非常实用。

4. 将时间格式化为指定的格式(YYYY-MM-DD HH:mm:ss)

/**
 * 格式化时间为 YYYY-MM-DD HH:mm:ss 格式
 * @param date 时间对象或可转换为时间对象的参数
 * @returns 格式化后的时间字符串
 */
export const formatTime = (date: Date | string | number) => {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  const seconds = String(d.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};

使用示例:

console.log(formatTime(new Date()));
console.log(formatTime('2023-05-20'));
console.log(formatTime(1684137600000));

5. NaN数据格式化处理

以下是关于NaN数据格式化处理的代码示例和说明:

代码实现

/**
 * NaN数据格式化处理
 * @param value 需要检查的值
 * @returns 处理后的数值
 */
export function NaNFormatter(value: any): number {
    return isNaN(value) ? 0 : value;
}

功能说明

该函数接受任意类型的输入值,检查是否为NaN(Not a Number),如果是则返回0,否则返回原值。

使用示例

console.log(NaNFormatter('abc'));  // 输出: 0
console.log(NaNFormatter(123));    // 输出: 123
console.log(NaNFormatter(NaN));    // 输出: 0

改进建议

对于更严格的类型检查,可以修改为以下版本:

export function NaNFormatter(value: unknown): number {
    return typeof value === 'number' && !isNaN(value) ? value : 0;
}

这个改进版会先检查输入值是否为number类型,再判断是否为NaN,避免非数字类型被强制转换。

6.  数字转汉字

以下是针对数字转汉字功能的优化实现和说明:

实现原理

函数使用两个数组分别存储数字和单位的中文表示,通过正则表达式匹配每个数字位并将其转换为对应的汉字和单位。

const units = ['', '十', '百', '千', '万', '十万', '百万', '千万', '亿'];
const digits = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九'];

优化改进

原始实现存在单位数组错误问题(如"十万"应为"万"),建议修改为更准确的单位表示:

const units = ['', '十', '百', '千', '万', '十', '百', '千', '亿'];

完整实现

改进后的完整函数实现:

export function numberToChinese(num: number): string {
    const units = ['', '十', '百', '千', '万', '十', '百', '千', '亿'];
    const digits = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
    
    const numStr = num.toString();
    let result = '';
    
    for (let i = 0; i < numStr.length; i++) {
        const digit = parseInt(numStr[i]);
        const unit = units[numStr.length - i - 1];
        result += digits[digit] + unit;
    }
    
    return result.replace(/^一十/, '十');
}

特殊情况处理

函数处理了"一十"开头的情况(如10转换为"十"而不是"一十"),但更复杂的零值处理可以进一步优化:

// 示例:1001 → "一千零一"而非"一千零零一"
result = result.replace(/零+/g, '零').replace(/零$/, '');

测试用例

示例测试结果:

console.log(numberToChinese(10));      // "十"
console.log(numberToChinese(100));     // "一百"
console.log(numberToChinese(1001));    // "一千零一"
console.log(numberToChinese(12345));   // "一万二千三百四十五"

7. 图片懒加载

该代码实现了一个基于Intersection Observer API的图片懒加载功能,适用于Vue或其他前端框架环境。

export const lazyImg = (el: string, arr: EmptyArrayType) => {
    const io = new IntersectionObserver((res) => {
        res.forEach((v: any) => {
            if (v.isIntersecting) {
                const {img, key} = v.target.dataset;
                v.target.src = img;
                v.target.onload = () => {
                    io.unobserve(v.target);
                    arr[key]['loading'] = false;
                };
            }
        });
    });
    nextTick(() => {
        document.querySelectorAll(el).forEach((img) => io.observe(img));
    });
};

实现原理

Intersection Observer API检测目标元素与视口的交叉状态,当图片进入可视区域时触发加载。代码中创建的观察者实例会监控所有匹配选择器的图片元素。

关键参数说明

  • el: string:需要观察的DOM元素选择器
  • arr: EmptyArrayType:存储图片状态的数组
  • data-img:自定义属性存储实际图片URL
  • data-key:自定义属性关联状态数组的索引

使用示例

<img data-img="real-image.jpg" data-key="0" class="lazy-image" src="placeholder.jpg">
// 在Vue组件中使用
import { lazyImg } from './lazyLoad';

const images = [
    { loading: true },
    { loading: true }
];

onMounted(() => {
    lazyImg('.lazy-image', images);
});

性能优化点

观察图片加载完成后调用unobserve停止观察,减少不必要的性能消耗。通过nextTick确保DOM更新完成后再建立观察关系。

注意事项

需要确保目标元素已添加data-imgdata-key属性。状态数组应与图片元素顺序对应,代码中未包含错误处理逻辑,实际使用时应补充。

8. 对象深克隆

该深克隆函数存在几个潜在问题,可以进一步优化以提高健壮性和功能性。

/**
 * 对象深克隆
 * @param obj 源对象
 * @returns 克隆后的对象
 */
export function deepClone<T>(obj: T): T {
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    const newObj = Array.isArray(obj) ? [] : {};

    Object.keys(obj).forEach(key => {
        newObj[key] = deepClone(obj[key]);
    });

    return newObj as T;
}

主要改进点

  1. 添加泛型支持,保留类型信息
  2. 处理原始值直接返回的情况
  3. 使用更可靠的Array.isArray判断数组
  4. 改用Object.keys遍历属性
  5. 移除try-catch改用更明确的类型判断

处理特殊类型扩展

对于Date、RegExp等特殊对象类型,可以进一步扩展:

export function deepClone<T>(obj: T): T {
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    if (obj instanceof Date) {
        return new Date(obj.getTime()) as T;
    }

    if (obj instanceof RegExp) {
        return new RegExp(obj) as T;
    }

    const newObj = Array.isArray(obj) ? [] : {};

    Object.keys(obj).forEach(key => {
        newObj[key] = deepClone(obj[key]);
    });

    return newObj as T;
}

性能优化考虑

对于大型对象,可以考虑使用结构化克隆API(现代浏览器支持):

export function deepClone<T>(obj: T): T {
    if (typeof structuredClone === 'function') {
        return structuredClone(obj);
    }
    // 降级到常规实现
    // ...
}

9. 判断是否是移动端

通过检测用户代理字符串(User Agent)可以判断当前设备是否为移动端。以下是一个实用的 JavaScript 函数实现:

/**
 * 判断是否是移动端
 */
export function isMobile() {
    return navigator.userAgent.match(
        /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
    ) !== null;
}

优化建议

  1. 正则表达式可以进一步扩展以覆盖更多移动设备类型。例如添加 TabletKindle 等关键词:
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|Tablet|Kindle)/i
  1. 对于现代浏览器,可以考虑使用 window.matchMedia 检测触屏支持:
export function isMobile() {
    return window.matchMedia("(max-width: 768px)").matches || 
           navigator.userAgent.match(/* 原有正则 */) !== null;
}
  1. 如果需要区分具体平台类型,可以拆分为独立检测函数:
export function isIOS() {
    return /iPhone|iPad|iPod/i.test(navigator.userAgent);
}

export function isAndroid() {
    return /Android/i.test(navigator.userAgent);
}

注意事项

  • 用户代理检测不是100%可靠,某些设备或浏览器可能伪装UA
  • 在服务器端检测时需要使用请求头中的 User-Agent
  • 移动端判断通常需要结合视口尺寸检测(如宽度小于768px)

10. 判断数组对象中所有属性是否为空,为空则删除当前行对象

以下是一个优化版本的函数,用于处理数组对象中空值属性并删除全空的行对象:

/**
 * 删除数组中所有属性为空的子对象
 * @param list 待处理的数组对象
 * @returns 过滤后的数组对象
 */
export function filterEmptyObjects<T extends Record<string, any>>(list: T[]): T[] {
    return list.filter(item => {
        return Object.values(item).some(value => value !== '');
    });
}

使用示例

const testData = [
    { name: 'John', age: 30, city: '' },
    { name: '', age: '', city: '' },
    { name: 'Alice', age: '', city: 'NYC' }
];

const result = filterEmptyObjects(testData);
console.log(result);
// 输出: [{ name: 'John', age: 30, city: '' }, { name: 'Alice', age: '', city: 'NYC' }]

注意事项

  • 该函数严格判断空字符串'',不会过滤其他假值如nullundefined
  • 如需扩展过滤条件,可修改判断逻辑:
Object.values(item).some(value => value !== '' && value !== null)

11.  加密处理

该函数使用CryptoJS库实现AES加密,以下是关键点分析:

const key = CryptoJS.enc.Utf8.parse(keyWord);

将密钥字符串转换为CryptoJS支持的WordArray格式,使用UTF-8编码处理。

var encrypted = CryptoJS.AES.encrypt(src, key, {
    iv: key,
    mode: CryptoJS.mode.CFB,
    padding: CryptoJS.pad.NoPadding,
});

加密配置包含三个重要参数:

  • iv:初始化向量,这里直接使用密钥作为IV
  • mode:选择CFB(Cipher Feedback)加密模式
  • padding:指定NoPadding表示不进行数据填充

使用注意事项

加密函数返回Base64格式的字符串结果,可直接用于传输或存储。需要配套的解密函数使用相同参数:

function decryption(encrypted: string, keyWord: string) {
    const key = CryptoJS.enc.Utf8.parse(keyWord);
    return CryptoJS.AES.decrypt(encrypted, key, {
        iv: key,
        mode: CryptoJS.mode.CFB,
        padding: CryptoJS.pad.NoPadding
    }).toString(CryptoJS.enc.Utf8);
}

安全建议

实际应用中建议:

  • IV应当随机生成而非固定值
  • CFB模式需要保证IV唯一性
  • 考虑使用PKCS7等标准填充方式
  • 密钥建议通过安全渠道分发

典型应用场景包括前端敏感数据传输、本地存储加密等。确保前后端使用相同的加密参数配置。

12.  解密

以下是针对AES解密函数的优化说明与实现细节:

函数参数说明

src为待解密的密文(Base64格式),keyWord为密钥字符串。密钥需转换为UTF-8格式的WordArray对象供CryptoJS使用。

密钥处理

const key = CryptoJS.enc.Utf8.parse(keyWord);

密钥需通过CryptoJS.enc.Utf8.parse转换为WordArray对象,确保与加密端一致。

解密配置

var decryptd = CryptoJS.AES.decrypt(src, key, {
    iv: key,              // 使用密钥作为初始化向量
    mode: CryptoJS.mode.CFB,  // 密码反馈模式
    padding: CryptoJS.pad.NoPadding  // 无填充模式
});
  • CFB模式无需对输入数据进行填充,故选用NoPadding
  • 注意:若加密端使用了填充(如PKCS7),此处需对应调整

返回结果处理

return decryptd.toString(CryptoJS.enc.Utf8);

解密结果通过toString()转为UTF-8明文。若解密失败可能返回空字符串或乱码。

注意事项

  1. 确保密钥与加密端完全一致(包括大小写和特殊字符)
  2. CFB模式要求IV与密钥长度相同,示例中使用密钥作为IV
  3. 生产环境建议添加异常捕获逻辑

完整代码示例:

export function decryption(src: string, keyWord: string): string {
    try {
        const key = CryptoJS.enc.Utf8.parse(keyWord);
        const decryptd = CryptoJS.AES.decrypt(src, key, {
            iv: key,
            mode: CryptoJS.mode.CFB,
            padding: CryptoJS.pad.NoPadding
        });
        return decryptd.toString(CryptoJS.enc.Utf8);
    } catch (e) {
        console.error('Decryption failed:', e);
        return '';
    }
}

13.  string 驼峰转下划线

以下是一个将驼峰命名法转换为下划线命名法的TypeScript函数实现,以及相关说明:

函数代码解析

export function toUnderline(str: string) {
    return str.replace(/([A-Z])/g, '_$1').toLowerCase();
}

实现原理

该函数使用正则表达式匹配所有大写字母,并在每个大写字母前添加下划线。然后整个字符串被转换为小写。

示例用法

const camelCase = 'userName';
const underscore = toUnderline(camelCase); // 输出: "user_name"

可选的改进版本

如果需要处理首字母大写的情况(避免开头出现下划线),可以使用以下改进版本:

export function toUnderline(str: string) {
    return str.replace(/([A-Z])/g, (match) => `_${match}`).toLowerCase().replace(/^_/, '');
}

测试用例

console.log(toUnderline('firstName'));    // 输出: "first_name"
console.log(toUnderline('LastName'));     // 输出: "last_name"
console.log(toUnderline('XMLHttpRequest')); // 输出: "xml_http_request"

这个方法简单高效地实现了驼峰命名到下划线命名的转换,适用于大多数常见的JavaScript/TypeScript命名转换场景。

14.   颜色转换函数

HEX转RGB (hexToRgb)

const hexToRgb = (str: string): any => {
    let hexs: any = '';
    let reg = /^\#?[0-9A-Fa-f]{6}$/;
    if (!reg.test(str)) {
        ElMessage.warning('输入错误的hex');
        return '';
    }
    str = str.replace('#', '');
    hexs = str.match(/../g);
    for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16);
    return hexs;
};
  • 输入格式校验:6位HEX(带或不带#)。
  • 处理逻辑:去除#后按2字符分段,转为十进制数值。

RGB转HEX (rgbToHex)

const rgbToHex = (r: any, g: any, b: any): string => {
    let reg = /^\d{1,3}$/;
    if (!reg.test(r) || !reg.test(g) || !reg.test(b)) {
        ElMessage.warning('输入错误的rgb颜色值');
        return '';
    }
    let hexs = [r.toString(16), g.toString(16), b.toString(16)];
    for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`;
    return `#${hexs.join('')}`;
};
  • 输入校验:RGB每个通道值需为0-255的整数。
  • 处理逻辑:十进制转十六进制,不足2位补零。

颜色加深 (getDarkColor)

const getDarkColor = (color: string, level: number): string => {
    let rgb = useChangeColor().hexToRgb(color);
    for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level));
    return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
};
  • 原理:通过降低RGB各通道亮度实现(原值 * (1 - level))。

颜色变浅 (getLightColor)

const getLightColor = (color: string, level: number): string => {
    let rgb = useChangeColor().hexToRgb(color);
    for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
    return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
};
  • 原理:基于当前值与白色(255)差值按比例混合(差值 * level + 原值)。

使用示例

const { getDarkColor, getLightColor } = useChangeColor();
const darkBlue = getDarkColor('#1a73e8', 0.2); // 加深20%
const lightBlue = getLightColor('#1a73e8', 0.2); // 变浅20%

注意事项

  • level参数范围需在0-1之间,否则可能产生无效颜色值。
  • RGB转HEX时,若输入值超出0-255范围可能导致异常结果。

15.  验证百分比(不可以小数)

/**
 * 验证百分比整数(0-100)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberPercentage(val: string): string {
    let v = val.replace(/\s/g, ''); // 去除所有空格
    
    // 只保留数字
    v = v.replace(/[^\d]/g, '');
    
    // 处理空字符串或纯0
    if (v === '' || v === '0') return '0';
    
    // 去除前导0
    v = v.replace(/^0+/, '');
    
    // 处理超过100的情况
    const numValue = parseInt(v, 10);
    if (numValue > 100) return '100';
    
    return v;
}

测试用例

// 测试示例
console.log(verifyNumberPercentage(' 50 '));    // "50"
console.log(verifyNumberPercentage('050'));     // "50" 
console.log(verifyNumberPercentage('100'));     // "100"
console.log(verifyNumberPercentage('101'));     // "100"
console.log(verifyNumberPercentage('0'));       // "0"
console.log(verifyNumberPercentage('00'));      // "0"
console.log(verifyNumberPercentage('abc50'));   // "50"
console.log(verifyNumberPercentage('50%'));     // "50"

说明

  1. 简化了空格处理逻辑,使用\s匹配所有空白字符
  2. 明确处理了空输入和纯0输入的情况
  3. 使用parseInt进行数值比较,逻辑更清晰
  4. 添加了更完备的测试用例
  5. 函数注释更准确地反映了功能限制(0-100整数)

该版本更好地处理了边界情况,代码可读性和健壮性都有所提升。

16.  验证百分比(可以小数)

export function verifyNumberPercentageFloat(val: string): string {
    let v = verifyNumberIntegerAndFloat(val);
    if (v === '') return '';
    
    // 处理超过100的情况
    const num = parseFloat(v);
    if (num > 100) return '100';
    
    // 处理100.的情况
    if (v.startsWith('100') && v !== '100') {
        return v.includes('.') && v.indexOf('.') === 3 ? 
               '100' : v.substring(0, 3);
    }
    
    return v;
}

单元测试建议

应覆盖以下测试用例:

// 正常值
assert.equal(verifyNumberPercentageFloat('50'), '50');
assert.equal(verifyNumberPercentageFloat('99.9'), '99.9');

// 边界值
assert.equal(verifyNumberPercentageFloat('100'), '100');
assert.equal(verifyNumberPercentageFloat('100.'), '100');
assert.equal(verifyNumberPercentageFloat('100.1'), '100');

// 异常值
assert.equal(verifyNumberPercentageFloat('101'), '100');
assert.equal(verifyNumberPercentageFloat('999'), '100');
assert.equal(verifyNumberPercentageFloat('-1'), '');

17.  正整数验证

该函数用于验证并处理用户输入的字符串,确保最终输出为正整数格式。以下是具体实现逻辑:

/**
 * 正整数验证
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifiyNumberInteger(val: string) {
	// 匹配空格
	let v = val.replace(/(^\s*)|(\s*$)/g, '');
	// 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12
	v = v.replace(/[\.]*/g, '');
	// 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323
	v = v.replace(/(^0[\d]*)$/g, '0');
	// 首位是0,只能出现一次
	v = v.replace(/^0\d$/g, '0');
	// 只匹配数字
	v = v.replace(/[^\d]/g, '');
	// 返回结果
	return v;
}

处理步骤说明

去除首尾空格 使用正则表达式 /(^\s*)|(\s*$)/g 匹配并移除字符串开头和结尾的所有空格字符。

去除小数点 通过 /[\.]*/g 正则表达式移除字符串中所有的小数点,防止用户输入类似"0.1.12.12"这样的非法数值。

处理前导零 正则表达式 /(^0[\d]*)$/g 将类似"00121323"的输入替换为单个"0",确保前导零不会影响数值的正确性。

修正单零后跟数字 表达式 /^0\d$/g 确保当首位为0且后面跟着其他数字时,替换为单个"0",防止用户输入类似"0123"这样的数值。

过滤非数字字符 最后使用 /[^\d]/g 正则表达式移除所有非数字字符,确保输出只包含纯数字。

使用示例

console.log(verifiyNumberInteger(" 0012.34a56 ")); // 输出: "123456"
console.log(verifiyNumberInteger("0.123"));       // 输出: "0123"
console.log(verifiyNumberInteger("abc123"));      // 输出: "123"

该函数适用于需要严格正整数输入的场景,如表单验证或数据处理前清洗。通过多步正则处理确保最终输出符合正整数格式要求。

18.  去掉中文及空格

/**
 * 移除字符串中的中文字符及所有空格(包括首尾和中间)
 * @param val 待处理的字符串
 * @returns 处理后的纯非中文且无空格字符串
 */
export function removeChineseAndSpaces(val: string): string {
    // 移除所有中文字符(Unicode范围)和所有类型的空格(包括全角空格)
    return val.replace(/[\u4e00-\u9fa5\u3000\s]/g, '');
}

测试用例

// 测试示例
console.log(removeChineseAndSpaces("Hello 世界"));  // "Hello"
console.log(removeChineseAndSpaces("  测试  "));    // ""
console.log(removeChineseAndSpaces("a b c"));       // "abc"

注意事项

  1. 该函数会移除字符串中的所有中文字符和空格
  2. 如需保留其他语言的字符(如日文、韩文等),需要调整正则表达式范围
  3. 严格模式下可考虑添加类型校验:
if (typeof val !== 'string') {
    throw new TypeError('Input must be a string');
}

19.  去掉英文及空格

以下是对提供的 TypeScript 函数的解析和改进建议,以及相关功能的扩展实现:

函数功能解析

当前函数 verifyEnAndSpace 主要实现两个功能:

  1. 移除字符串中的所有英文字母(大小写)
  2. 移除字符串首尾的空格
export function verifyEnAndSpace(val: string) {
    let v = val.replace(/[a-zA-Z]+/g, '');
    v = v.replace(/(^\s*)|(\s*$)/g, '');
    return v;
}

改进建议版本

优化正则表达式合并为单次匹配,提升效率:

export function removeEnglishAndTrim(val: string) {
    return val.replace(/[a-zA-Z]/g, '').trim();
}

扩展功能实现

如果需要更全面的字符过滤功能,可以参考以下实现:

/** 移除特定字符类型 */
export function filterCharacters(
    str: string,
    options: {
        english?: boolean;
        spaces?: boolean;
        numbers?: boolean;
        symbols?: boolean;
    }
) {
    let pattern = '';
    if (options.english) pattern += 'a-zA-Z';
    if (options.numbers) pattern += '0-9';
    if (options.symbols) pattern += '\\W';
    if (options.spaces) pattern += '\\s';

    return pattern 
        ? str.replace(new RegExp(`[${pattern}]`, 'g'), '').trim()
        : str.trim();
}

使用示例

// 基础用法
const cleanStr = removeEnglishAndTrim(' Hello 123 World! ');
console.log(cleanStr); // "123 !"

// 高级过滤
const filtered = filterCharacters('Test 123!', {
    english: true,
    spaces: true
});
console.log(filtered); // "123!"

以上实现提供了更灵活的参数化控制,可以根据需要移除数字、符号等特定字符类别。正则表达式采用动态构建模式,通过选项对象控制需要过滤的字符类型。

20.  禁止输入空格

/**
 * 禁止输入空格
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyAndSpace(val: string) {
    // 匹配空格
    let v = val.replace(/(^\s*)|(\s*$)/g, '');
    // 返回结果
    return v;
}

功能说明

该函数用于去除字符串首尾的空格,确保输入内容不含开头和结尾的空白字符。适用于表单验证、输入框处理等场景。

正则表达式解析

/(^\s*)|(\s*$)/g 分解如下:

  • ^\s* 匹配开头处的零个或多个空白字符
  • \s*$ 匹配结尾处的零个或多个空白字符
  • | 表示或逻辑
  • g 表示全局匹配

使用示例

// 去除首尾空格示例
const input1 = "   hello world   ";
console.log(verifyAndSpace(input1));  // 输出: "hello world"

const input2 = "noSpacesHere";
console.log(verifyAndSpace(input2));  // 输出: "noSpacesHere"

注意事项

函数仅处理字符串首尾空格,不会去除字符串中间的空格。若需去除所有空格可修改正则表达式为:/\s+/g

21.数字转中文大写

该函数将数字转换为中文大写金额形式,适用于财务、发票等场景。以下是关键实现逻辑说明:

export function verifyNumberCnUppercase(val: any, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') {
    val += '00';
    let lookup = val.indexOf('.');
    if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2);
    unit = unit.substr(unit.length - val.length);
    for (let i = 0; i < val.length; i++) {
        v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1);
    }
    v = v
        .replace(/零角零分$/, '整')
        .replace(/零[仟佰拾]/g, '零')
        .replace(/零{2,}/g, '零')
        .replace(/零([亿|万])/g, '$1')
        .replace(/零+元/, '元')
        .replace(/亿零{0,3}万/, '亿')
        .replace(/^元/, '零元');
    return v;
}

关键处理步骤

数值预处理 添加'00'确保小数部分有两位,统一处理整数和小数。若存在小数点,移除小数点并保留两位小数。

val += '00';
let lookup = val.indexOf('.');
if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2);

单位对齐 根据输入数值长度截取单位字符串,保持数值与单位一一对应。

unit = unit.substr(unit.length - val.length);

字符转换 遍历每位数字,转换为对应中文大写并拼接单位。

for (let i = 0; i < val.length; i++) {
    v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1);
}

正则优化 处理连续零、特殊单位等场景,使结果符合中文大写金额规范。

v = v
    .replace(/零角零分$/, '整')
    .replace(/零[仟佰拾]/g, '零')
    .replace(/零{2,}/g, '零')
    .replace(/零([亿|万])/g, '$1')
    .replace(/零+元/, '元')
    .replace(/亿零{0,3}万/, '亿')
    .replace(/^元/, '零元');

使用示例

输入数字12345.67,输出结果为壹万贰仟叁佰肆拾伍元陆角柒分

console.log(verifyNumberCnUppercase('12345.67'));
// 输出:壹万贰仟叁佰肆拾伍元陆角柒分

22.  IP地址验证

该函数使用正则表达式验证输入的字符串是否符合IPv4地址格式。IPv4地址由四个0-255之间的数字组成,用点号分隔。

export function verifyIPAddress(val: string) {
    if (!/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(val))
        return false;
    else return true;
}

正则表达式解析

该正则表达式可以分为以下几个部分:

  1. (\d{1,2}|1\d\d|2[0-4]\d|25[0-5])匹配0-255之间的数字
    • \d{1,2}匹配0-99
    • 1\d\d匹配100-199
    • 2[0-4]\d匹配200-249
    • 25[0-5]匹配250-255
  2. 每个数字部分后面跟着一个点号,最后一个数字后面没有点号

改进建议

该函数可以简化为直接返回正则表达式测试结果:

export function verifyIPAddress(val: string) {
    return /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/.test(val);
}

也可以考虑使用更现代的IPv6验证,或者两者结合的验证方式:

export function verifyIPAddress(val: string) {
    return /^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(val) || 
           /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/.test(val);
}

23.  邮箱验证

const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

export function verifyEmail(val: string): boolean {
    return EMAIL_REGEX.test(val);
}

边界情况处理

测试案例应包括以下场景:

// 合法邮箱
verifyEmail('user@example.com');  // true
verifyEmail('first.last@sub.domain.com');  // true

// 非法邮箱
verifyEmail('plainaddress');  // false
verifyEmail('@missing-local.com');  // false
verifyEmail('user@.com');  // false

性能考虑

正则表达式预编译可避免每次调用时重新编译 简单验证场景下,该正则表达式性能足够 如需更严格验证,可考虑RFC 5322标准正则表达式

24.  身份证验证

export function rigorousIdCardValidation(val: string) {
  // 基础格式检查
  if (!/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/i.test(val)) {
    return false;
  }
  
  // 行政区划校验
  if (!validateAreaCode(val)) return false;
  
  // 日期校验
  if (!validateBirthDate(val)) return false;
  
  // 校验码验证
  return verifyIdCardAdvanced(val);
}

实际应用中建议:

  • 前端进行基础格式验证
  • 后端进行完整校验
  • 对于15位旧身份证需要单独处理
  • 港澳台居民居住证需要不同的验证规则

25.  车牌号验证

/**
 * 车牌号验证
 * @param val 当前值字符串
 * @returns 返回 true:车牌号正确
 */
export function verifyCarNum(val: string) {
    // false: 车牌号不正确
    if (
        !/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(
            val
        )
    )
        return false;
    // true:车牌号正确
    else return true;
}

正则表达式分解

该正则表达式主要分为两部分,分别对应两种车牌号格式:

  1. 新能源车牌格式
    ([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4}))

    • 地区简称(如京、沪) + 字母(A-Z)
    • 两种新能源车牌格式:
      • 5位数字 + D或F(如12345D
      • D或F + 1位字母或数字 + 4位数字(如D1A234
  2. 普通车牌格式
    ([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领])

    • 地区简称 + 字母(A-Z) + 4位字母或数字 + 1位结尾字符(如挂、学、警等)

使用示例

console.log(verifyCarNum("京A12345"));    // false(不符合新能源或普通车牌格式)
console.log(verifyCarNum("京AD12345"));   // true(新能源车牌)
console.log(verifyCarNum("京A1234警"));   // true(普通车牌带警字)

注意事项

  • 地区简称需为现行有效的行政区划(如京津沪渝等)。
  • 新能源车牌以DF结尾或开头。
  • 普通车牌最后一位可以是数字、字母或特殊字(如挂、学、警等)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值