Skip to content

工具函数

一些常见的工具函数

color

mix(模拟 SCSS mix() 函数,混合两种颜色)

typescript
/**
 * 颜色相关的处理
 *
 * @author 左建
 * @exports mix, darken,  light
 */
/**
 * 模拟 SCSS mix() 函数,混合两种颜色
 *
 * @param color1 第一种颜色(十六进制,如 #1963dc)
 * @param color2 第二种颜色(十六进制,如 #ffffff)
 * @param weight 第一种颜色的权重(0-100 或 "0%-100%",默认 50)
 * @returns 混合后的十六进制颜色
 */
export declare function mix(color1: string, color2: string, weight?: number | string): string;

light(与白色混合,传10表示变浅到原来的10%, 注意这点是变浅到原来10%, 意思是传10只有传入颜色的10%,很浅)

typescript
/**
 * 与白色混合,传10表示变浅到原来的10%, 注意这点是变浅到原来10%, 意思是传10只有传入颜色的10%,很浅
 *
 * @param color 第一种颜色(十六进制,如 #1963dc)
 * @param weight 第一种颜色的权重(0-100 或 "0%-100%",默认 50)
 * @returns 混合后的十六进制颜色
 */
export declare function light(color: string, weight?: number | string): string;

darken(与黑色混合 传10表示加深10%,注意这点是加深10%,意思是传入颜色加深10%)

typescript
/**
 * 与黑色混合 传10表示加深10%,注意这点是加深10%,意思是传入颜色加深10%
 *
 * @param color 第一种颜色(十六进制,如 #1963dc)
 * @param weight 第一种颜色的权重(0-100 或 "0%-100%",默认 50)
 * @returns 混合后的十六进制颜色
 */
export declare function darken(color: string, weight?: number | string): string;

event-emitter

typescript
type FnType = (...args: any[]) => void;

EventEmitter(事件发射器)

typescript
/**
 * 事件发射器
 *
 * @class
 * @class
 */
export default class EventEmitter {
    private events;
    private paddingEvents;
    constructor();
    /**
     * 监听事件
     *
     * @param event 事件名称
     * @param callback 回调函数
     */
    on(event: string | Array<string>, callback: FnType): void;
    /**
     * 移除监听事件,如果不传任何参数,则清空所有
     *
     * @param event 事件名称
     * @param callback 回调函数,如果不传则清空该事件下的所有侦听
     */
    off(event?: string | Array<string>, callback?: FnType): void;
    /**
     * 监听一次事件
     *
     * @param event 事件名称
     * @param callback 回调函数
     */
    once(event: string, callback: FnType): void;
    /**
     * 触发事件
     *
     * @param event 事件名称
     * @param args 回调函数的参数
     */
    emit(event: string, ...args: any[]): void;
}

load

typescript
type TaskType = () => Promise<any>;

loadTaskWithRetry(带有错误重试功能的加载函数)

typescript
/**
 * 带有错误重试功能的加载函数
 *
 * @param task 任务
 * @param onError 错误时的回调
 */
export declare function loadTaskWithRetry(task: TaskType, onError?: (retry: Function, fail: Function) => void): Promise<any>;

loadTaskRetryFixCount(固定重试次数)

typescript
/**
 * 固定重试次数
 *
 * @param task 任务
 * @param count 重试次数,默认一次
 */
export declare function loadTaskRetryFixCount(task: TaskType, count?: number): Promise<any>;

TaskQueen(异步任务队列)

typescript
/**
 * 异步任务队列
 *
 * @class
 * @class
 * @param limit 队列的窗口大小,默认为3
 */
export declare class TaskQueen {
    private runningCount;
    private limit;
    private queen;
    /**
     * 构造函数
     *
     * @param limit 队列的窗口大小,默认为3
     */
    constructor(limit?: number);
    /**
     * 运行任务
     *
     * @param task 任务
     */
    run(task: TaskType): Promise<void>;
}

loadTasks(批量执行任务)

typescript
/**
 * 批量执行任务
 *
 * @param tasks 任务
 * @param success 成功回调
 * @param fail 失败回调
 * @param windowSize 窗口大小
 */
export declare function loadTasks(tasks: TaskType[], success?: (res: any, index: number) => void, fail?: (err: any, index: number) => void, windowSize?: number): void;

utils

sleep(等待多少秒钟,单位为毫秒)

typescript
/**
 * 等待多少秒钟,单位为毫秒
 *
 * @example
 *     sleep(20).then(() => {
 *     // 做点什么
 *     }) 等待20毫秒之后
 *
 * @param ms 传入的值
 */
export declare function sleep(ms: number): Promise<void>;

isObject(是否是对象)

typescript
/**
 * 是否是对象
 *
 * @example
 *     isObject({}) => true; isObject([]) => false
 *
 * @param value 传入的值
 */
export declare function isObject(value: any): boolean;

deepClone(深度克隆, 会克隆原型和symbol)

typescript
/**
 * 深度克隆, 会克隆原型和symbol
 *
 * @example
 *     deepClose({a: 1, b: 2, c: {d: 'e'}, f: [1, 2], g: Symbol('f'), date: new Date()}) =>
 *     新对象{a: 1, b: 2, c: {d: 'e'}, f: [1, 2], g: Symbol('f'), date: xxx}, date为以前的对象
 *     这点针对普通对象和数组进行克隆,其他对象不进行任何操作
 *
 * @param value 传入的指
 */
export declare function deepClone<T>(value: T): T;

isArrayOrObject(是否是普通对象或者数组)

typescript
/**
 * 是否是普通对象或者数组
 *
 * @example
 *     isArrayOrObject({}) => true
 *     isArrayOrObject([]) => true
 *     isArrayOrObject(new Date()) => false
 *     isArrayOrObject(new Set()) => false
 *     .... 其他均为false
 *
 * @param value 传入的指
 */
export declare function isArrayOrObject(value: any): boolean;

merge(合并对象)

typescript
/**
 * 合并对象
 *
 * @example
 *     const target = {a: 'b', e: [2, {f: 'd'}, {g: 'h'}] }; const source = {c: 'd', e: [1]}
 *     merge(target, false, source) => {a: 'b', c: 'd', e: [1]}
 *     merge(target, true, source) => {a: 'b', c: 'd', e: [1, {f: 'd'}, {g: 'h'}]}
 *
 * @param target 目标对象
 * @param mergeArray 是否合并数组
 * @param sources 源对象
 */
export declare function merge(target: any, mergeArray: boolean, ...sources: any[]): any;

isEmpty(判断值是否为空)

typescript
/**
 * 判断值是否为空
 *
 * @example
 *     // 默认将0也判定为空
 *     isEmpty(0) => true
 *     // 将0判定为不为空
 *     isEmpty(0, false) => false
 *
 *     // 空对象判定为空
 *     isEmpty({}) => true;
 *     // 空数组判定为空
 *     isEmpty([]) => true
 *
 * @param value 判断值, 常规的空值:'', null, undefined, NaN, false 等都会判定为空
 * @param isIncludeZero 是否包含0
 */
export declare function isEmpty(value: any, isIncludeZero?: boolean): boolean;

isNotEmpty(判断值是否不为空,相当于 !isEmpty(value))

typescript
/**
 * 判断值是否不为空,相当于 !isEmpty(value)
 *
 * @example
 *     // 默认将0也判定为0
 *     isNotEmpty(0) => false
 *     // 将0判定为不为空
 *     isNotEmpty(0, false) => true
 *
 *     // 空对象判定为空
 *     isNotEmpty({}) => false;
 *     // 空数组判定为空
 *     isNotEmpty([]) => false
 *
 * @param value 判断值, 常规的空值:'', null, undefined, NaN, false 等都会判定为空
 * @param isIncludeZero 是否包含0
 */
export declare function isNotEmpty(value: any, isIncludeZero?: boolean): boolean;

addPercentage(数字后面添加 %)

typescript
/**
 * 数字后面添加 %
 *
 * @example
 *     addPercentage(10) => 10%
 *     addPercentage(0.4569, true) => 45.7%
 *     addPercentage('10%') => 10%
 *     其他类型的值 返回空字符串
 *
 * @param value 传入的数值
 * @param isDecimal 是否处理小数:0.8534 => 85.3
 */
export declare function addPercentage(value: any, isDecimal?: boolean): string;

getPropertyValueByPath(从对象中获取属性值)

typescript
/**
 * 从对象中获取属性值
 *
 * @example
 *     const obj = {a:{b: [1]}}
 *     getPropertyValueByPath(obj, 'a.b[0]') => 1
 *     getPropertyValueByPath(obj, 'a.b[1]', '--') => --
 *
 * @param obj 传入的对象
 * @param path 传入的path路径:a.b[0].c
 * @param placeholder 为空时的占位符
 */
export declare function getPropertyValueByPath(obj: Record<any, any>, path: string, placeholder?: any): any;

setPropertyValueByPath(设置对象的属性值)

typescript
/**
 * 设置对象的属性值
 *
 * @example
 *     const obj = {a:{b: [[{e: 'd'}]]}}
 *     setPropertyValueByPath(obj, 'a.b[0][1].c', 'g') => {a:{b: [[{e: 'd'}, {c: 'g'}]]}}
 *
 * @param obj 传入的对象
 * @param path 传入的path路径
 * @param value 设置的值
 */
export declare function setPropertyValueByPath<T>(obj: T, path: string, value: any): T;

kebabToCamelCase(Kebab("-"分割)转为小驼峰(第一个单词全小写,后续单词首字母大写))

typescript
/**
 * Kebab("-"分割)转为小驼峰(第一个单词全小写,后续单词首字母大写)
 *
 * @example
 *     kebabToCamelCase('hello-world') => helloWorld
 *     kebabToCamelCase('Hello-World') => helloWorld
 *     kebabToCamelCase('HeLlo') => hello
 *
 * @param str 输入的横杠分隔字符串(如 "hello-world"或"Hello-World")=> helloWorld
 * @returns 小驼峰格式字符串(如 "helloWorld")
 */
export declare function kebabToCamelCase(str: string): string;

camelCaseToKebab(小驼峰转为kebab("-"分割))

typescript
/**
 * 小驼峰转为kebab("-"分割)
 *
 * @example
 *     camelCaseToKebab("helloWorld") => hello-world
 *     camelCaseToKebab("FooBar") => foo-bar
 *
 * @param str 输入的横杠分隔字符串(如 "helloWorld"或"HelloWorld")=> hello-world
 * @returns 小驼峰格式字符串(如 "hello-world")
 */
export declare function camelCaseToKebab(str: string): string;

getCameCaseObject(将对象键转为小驼峰)

typescript
/**
 * 将对象键转为小驼峰
 *
 * @example
 *     const obj = {a: 'b', 'foo-bar': 'fooBar', CameCase: 'CameCase'}
 *     getCameCaseObject(obj) => {a: 'b', fooBar: 'fooBar', cameCase: 'CameCase'}
 *
 * @param object 传入的对象
 */
export declare function getCameCaseObject<T>(object: T): T;

noop(空函数,常用于占位,避免重复创建函数)

typescript
/** 空函数,常用于占位,避免重复创建函数 */
export declare function noop(): void;

polling(轮询函数, 带有暂停和恢复执行)

typescript
/**
 * 轮询函数, 带有暂停和恢复执行
 *
 * @example
 *     const task = async () => {}
 *     const pollHandler = polling(task)
 *     pollHandler.paused() // 暂停
 *     pollHandler.resumed() // 恢复执行
 *
 * @param task 轮询一个Promise任务
 * @param success 成功时的回调
 * @param fail 失败的回调
 * @param immediate 是否立即开始
 * @param step 每一次轮询后,增加的时间,单位毫秒
 * @param startWaitTime 初始等待时间(毫秒)
 */
export declare function polling(task: () => Promise<any>, success?: (res: any) => void, fail?: (res: any) => void, immediate?: boolean, step?: number, startWaitTime?: number): {
    /** 暂停执行 */
    paused(): void;
    /**
     * 恢复执行
     *
     * @param isResetTime 是否重置等待时间为startWaitTime
     */
    resumed(isResetTime?: boolean): void;
};

isPrimitive(判断一个值是否是原始类型)

typescript
/**
 * 判断一个值是否是原始类型
 *
 * @example
 *     isPrimitive(对象) => false
 *     isPrimitive(() => {}) => false
 *     其他情况均为true
 *
 * @param value 传入的值
 */
export declare function isPrimitive(value: any): boolean;

isEquals(判断两个值是否相等, 原始值通过Object.is判断,非原始值递归判断)

typescript
/**
 * 判断两个值是否相等, 原始值通过Object.is判断,非原始值递归判断
 *
 * @example
 *     isEquals('foo', 'bar') => false
 *     isEquals({a: 'b', c: {d: 'e'}}, 'bar') => false
 *     isEquals({a: 'b', c: {d: 'e'}}, {a: 'b', c: {d: 'e'}}) => true
 *
 * @param v1 值一
 * @param v2 值二
 */
export declare function isEquals(v1: any, v2: any): boolean;

uniqueArray(数组去重,重的概念:原始类型用Object.is比较,非原始类型递归Object.is比较)

typescript
/**
 * 数组去重,重的概念:原始类型用Object.is比较,非原始类型递归Object.is比较
 *
 * @example
 *     // 内部使用isEquals去比较
 *     uniqueArray([{a: 'b', c: 'd'}, { a: 'b' }, {a: 'b'}, 1, 1, 'foo', 'foo', 'bar']) => [{a: 'b', c: 'd'}, {a: 'b'}, 1,'foo','bar']
 *
 * @param list 需要去重的数组
 */
export declare function uniqueArray<T>(list: Array<T>): T[];

formatDate(格式化时间)

typescript
/**
 * 格式化时间
 *
 * @example
 *     formatDate() => 当前时间,比如:2025-10-10
 *     formatDate(new Date(2021, 9, 15, 23, 59, 9), 'yyyy-mm-dd hh:MM:ss') => 2021-10-15 23:59:09
 *
 * @param dateTime 需要格式化的时间戳
 * @param formatStr 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
 * @returns 返回格式化后的字符串
 */
export declare function formatDate(dateTime?: any, formatStr?: string): string;

timeFrom(时间戳转为多久之前)

typescript
/**
 * 时间戳转为多久之前
 *
 * @example
 *     // 以当前时间为基准
 *     timeFrom() => 刚刚
 *     // 指定时间距离当前时间过去了多少
 *     timeFrom(new Date(2025, 9, 10, 18, 10, 9).getTime()) => 2025-10-10 或 刚刚 或 几分钟前 或 几个小时前 或 几天前
 *     timeFrom(new Date(2025, 9, 10, 18, 10, 9).getTime(), 'yyyy-mm-dd hh:MM:ss') => 2025-10-10 18:10:09 或 刚刚 或 几分钟前 或 几个小时前 或 几天前
 *     timeFrom(new Date(2025, 9, 10, 18, 10, 9).getTime(), false) => 2025-10-10 或 刚刚 或 几分钟前 或 几个小时前 或 几天前 或 几个月前 或 几年前
 *
 * @param timestamp 时间戳
 * @param format 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式; 如果为布尔值false,无论什么时间,都返回多久以前的格式
 * @returns 转化后的内容
 */
export declare function timeFrom(timestamp?: null | string | number, format?: string | false): string;

genSkus(生成sku数组,数组里面每一项都是一条sku组合,其实就是计算笛卡尔积。)

typescript
/**
 * 生成sku数组,数组里面每一项都是一条sku组合,其实就是计算笛卡尔积。
 *
 * @example
 *     genSkus({color: ['red', 'green', 'blue'], shape: ['circle', 'round'], size: ['small', 'medium', 'large']}) =>
 *     生成 [{color: 'red', size: 'small', shape: 'circle'}, ...]
 *
 * @param attrs 属性列表
 * @returns Skus数组
 */
export declare function genSkus<T extends Record<string, readonly any[]>>(attrs: T): Array<{
    [K in keyof T]: T[K][number];
}>;

normalizeUrl(去除地址中前后的斜杠)

typescript
/**
 * 去除地址中前后的斜杠
 *
 * @example
 *     normalizeUrl('//a/b/c//') => 'a/b/c'
 *     normalizeUrl('/a/b/c/') => 'a/b/c'
 *
 * @param url 属性列表
 */
export declare function normalizeUrl(url: string): string;