2024-10-05 更新:优化 deepFreeze

2024-09-04 更新:优化 deepFreezearrayBufferToBase64 等函数实现

一些自用 js 工具函数~

/**
 * 计算文本长度,英文 1 个算字符,非英文 2 算个字符
 * @param {String} text 文本
 * @returns {Number} length 文本长度
 */
export function countTextLength(text) {
  if (text === null) {
    return 0;
  }
  const match = text.match(/[^\x20-\xff]/g);
  if (match) {
    return match.length * 2 + text.length - match.length;
  }
  return text.length;
}

export function limitLength(e, maxLength = 32) {
  const input = e.target;
  while (countTextLength(input.value) > maxLength) {
    input.value = input.value.substring(0, input.value.length - 1);
  }
}

/**
 * 统计数组元素出现次数
 * @param {Array} list 数组
 * @returns {Map} 统计结果 Map 对象
 */
export function countTimes(list) {
  return list.reduce((m, x) => m.set(x, (m.get(x) || 0) + 1), new Map());
}

/**
 * 深度冻结非循环引用对象
 * @param object {Object | Array}
 * @return {Object | Array}
 */
export const deepFreeze = (object) => {
  if (object=== null || typeof object !== 'object') {
    return object;
  }
  Reflect.ownKeys(object).reduce((_, name) => {
    const value = object[name];
		if (value && typeof value === 'object') {
			deepFreeze(value);
		}
	}, null);
  return Object.freeze(object);
}

/**
 * 判断前一个数组是否包含后一个数组
 * @param {Array} array
 * @param {Array} sub
 * @returns {Boolean}
 */
export const contains = (array, sub) => sub.every((element) => array.includes(element));

/**
 * 获取两个数组的交集,返回一个数组
 * @param {Array} a
 * @param {Array} b
 * @returns {Array}
 */
export const intersection = (a, b) => a?.filter((v) => b?.includes(v)) || [];

/**
 * 获取两个数组的差集,返回一个数组
 * @param {Array} a
 * @param {Array} b
 * @returns {Array}
 */
export const difference = (a, b) => a?.concat(b)?.filter((v) => !a?.includes(v) || !b?.includes(v)) || [];

/**
 * 生成指定范围的数字数组,结束数字小于开始数字时返回为倒序
 * @param start { Number } 开始数字
 * @param stop { Number } 结束数字
 * @param step { Number } 每次递增大小
 * @return { Array }
 */
export const range = (start, stop, step = 1) => Array.from({ length: Math.abs(stop - start) / step + 1 }, (_, i) => stop >= start ? start + i * step : start - i * step);


export function decimalRound(number, n) {
    number = Number(number);
    if (Number.isNaN(number) || !number) {
      return 0;
    }
    return Math.round(Number.parseFloat(number) * (10 ** n)) / (10 ** n);
}


export const arrayBufferToBase64 = buffer => {
  const binary = new Uint8Array(buffer).reduce((accumulator, value) => accumulator + String.fromCharCode(value), '');
  return window.btoa(binary);
}

/**
 * 处理函数重载的函数
 * @param object 需要重载的函数所在的对象
 * @param name 需要重载的函数名称
 * @param fn 重载函数的实现,参数列表末位参数是默认参数时,总是执行参数列表 length 为实参列表 length+1 的那个函数
 */
export function overloadMethod(object, name, fn) {
    //把前一次添加的方法存在一个临时变量old里面
    const old = object[name];
    // 重写了object[name]的方法
    object[name] = function() {
        if (fn.length === arguments.length) {
            // 如果调用object[name]方法时,传入的参数个数跟预期的一致,则直接调用
            return fn.apply(this, arguments);
        } else if (typeof old === 'function') {
            // 否则,判断old是否是函数,如果是,就调用old
            return old.apply(this, arguments);
        }
    };
}

一个在学日本語的前端程序猿