目录

超实用的 TS/JS Snippet 集锦

零延时计时器

在浏览器中,setTimeout()/setInterval() 的每调用一次定时器的最小间隔是 4ms,这通常是由于函数嵌套导致(嵌套层级达到一定深度)。

此函数模拟一个零延时的 setTimeout,通过 postMessagemessage 事件来实现。避免浏览器中 setTimeoutsetInterval 的延迟。

ts 复制代码
(function () {
  var timeouts = [];
  var messageName = 'zero-timeout-message';

  // 保持 setTimeout 的形态,只接受单个函数的参数,延迟始终为 0。
  function setZeroTimeout(fn) {
    timeouts.push(fn);
    window.postMessage(messageName, '*');
  }

  function handleMessage(event) {
    if (event.source == window && event.data == messageName) {
      event.stopPropagation();
      if (timeouts.length > 0) {
        var fn = timeouts.shift();
        fn();
      }
    }
  }

  window.addEventListener('message', handleMessage, true);

  // 把 API 添加到 window 对象上
  window.setZeroTimeout = setZeroTimeout;
})();

findLast

从数组中查找满足条件的最后一个元素,返回该元素或 undefined

ts 复制代码
/**
 * Finds the last element in the array that satisfies the provided predicate function.
 * 
 * @param array The array to search.
 * @param predicate The condition function to evaluate each element.
 * @returns The last element that satisfies the predicate, or undefined if none do.
 */
function findLast<T>(array: Array<T>, predicate: (value: T, index: number, obj: T[]) => boolean): T | undefined {
  let cursor = array.length;

  while (cursor--) {
    if (predicate(array[cursor], cursor, array)) {
      return array[cursor];
    }
  }

  return undefined;
}

Clone Deep

深度复制一个对象或数组,避免引用问题。

ts 复制代码
/**
 * Creates a deep copy of a value, preserving the structure of objects and arrays.
 * 
 * @param value The value to be cloned.
 * @returns A deep clone of the input value.
 */
function cloneDeep<T>(value: T): T {
  if (typeof value !== 'object') {
    return value;
  }

  if (Array.isArray(value)) {
    return value.map(cloneDeep) as typeof value;
  }

  return Object.keys(value).reduce((acc, key) => {
    acc[key as keyof T] = cloneDeep(value[key as keyof T]);
    return acc;
  }, {} as T);
}

数组切割

将一个数组分割成多个小数组,每个小数组的长度不超过 chunkSize

ts 复制代码
/**
 * Splits an array into chunks of a given size.
 * 
 * @param array The array to split.
 * @param chunkSize The size of each chunk.
 * @returns An array of arrays, where each inner array is a chunk.
 */
function split(array: any[], chunkSize: number) {
  const result = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    result.push(array.slice(i, i + chunkSize));
  }

  return result;
}

Omit

创建一个新的对象,去除指定的属性。

ts 复制代码
/**
 * Creates a new object with the specified keys omitted.
 * 
 * @param object The original object.
 * @param keys The keys to omit from the object.
 * @returns A new object without the omitted keys.
 */
function omit<T, K extends keyof T>(object: T, keys: K[]) {
  const stringKeys = new Set(keys.map(String));
  const savedKeys = Object.keys(object).filter(
    (key) => !stringKeys.has(key)
  ) as Array<Exclude<keyof T, K>>;

  return pick(object, savedKeys);
}

Pick

从对象中挑选指定的属性,生成一个新的对象。

ts 复制代码
/**
 * Creates a new object with only the truthy values of the specified keys.
 * 
 * @param object The original object.
 * @param keys The keys to check for truthy values.
 * @returns A new object with truthy values only.
 */
function pick<T, K extends keyof T>(object: T, keys: K[]) {
  return keys.reduce((result, key) => {
    if (object[key]) {
      result[key] = object[key];
    }

    return result;
  }, {} as Pick<T, K>);
}

遍历对象,生成一个新对象

对对象的每个值进行转换,并生成一个新对象。

ts 复制代码
/**
 * Iterates through an object and generates a new object with the transformed values.
 * 
 * @param byKey The original object.
 * @param callback The function that transforms each value.
 * @returns A new object with the transformed values.
 */
export function mapValues<R extends any, M extends any>(
  byKey: CollectionByKey<M>,
  callback: (
    member: M,
    key: string,
    index: number,
    originalByKey: CollectionByKey<M>
  ) => R
): CollectionByKey<R> {
  return Object.keys(byKey).reduce(
    (newByKey: CollectionByKey<R>, key, index) => {
      newByKey[key] = callback(byKey[key], key, index, byKey);
      return newByKey;
    },
    {}
  );
}

arrayToRecord

将数组转换为以某个字段为键的对象。

ts 复制代码
/**
 * Converts an array of objects to a record (key-value pair) based on a specified key.
 * 
 * @param arr The array to convert.
 * @param key The key to use for each object in the array.
 * @returns A record where each key is the value of the specified key in the objects.
 */
const arrayToRecord = <K extends string | number | symbol, V extends { [key in K]?: any }>(
  arr: V[],
  key: K,
): Record<string, V> => {
  const record: Record<string, V> = {} as Record<K, V>;
  if (!Array.isArray(arr)) {
    return {} as Record<K, V>;
  }
  arr.forEach(item => {
    if (key in item) {
      record[item[key]] = item;
    }
  });
  return record;
};

arrayToMap

将数组转换为以某个字段为键的 Map 对象。

ts 复制代码
/**
 * Converts an array of objects to a Map based on a specified key.
 * 
 * @param array The array to convert.
 * @param key The key to use as the map's key.
 * @returns A Map where each key is the value of the specified key in the objects.
 */
const arrayToMap = <T, K extends keyof T>(array: T[], key: K): Map<T[K], T> => {
  const map = new Map<T[K], T>();
  for (const item of array) {
    if (item[key] !== undefined) {
      map.set(item[key], item);
    }
  }
  return map;
};

arrayGroupByKey

将数组根据某个字段的值进行分组,返回一个分组后的对象。

ts 复制代码
/**
 * Groups an array of objects by the value of a specified key.
 * 
 * @param array The array to group.
 * @param key The key to group the array by.
 * @returns An object where each key is a group key, and the value is an array of items in that group.
 */
const arrayGroupByKey = <T, K extends keyof T>(array: T[], key: K) =>
  array.reduce(
    (acc, cur) => {
      const groupKeyValue: any = cur[key];
      const prevItems = acc[groupKeyValue] ?? [];
      return {
        ...acc,
        [groupKeyValue]: [...prevItems, cur],
      };
    },
    {} as Record<string | number, T[]>,
  );

计算中英文字符串的长度

计算字符串的长度,中文字符算作 2 个单位,英文字符算作 1 个单位。

ts 复制代码
/**
 * Checks the length of a string where English characters count as 1, and Chinese characters count as 2.
 * 
 * @param str The string to check.
 * @returns The total length considering Chinese characters as double.
 */
const checkValueSize = str => {
  let rxcn = /[\u4e00-\u9fa5]/,
    num = 0
  for (let i = 0, j = str.length; i < j; i++) {
    let chr = str.charAt(i)
    if (rxcn.test(chr)) {
      num += 2
    } else {
      num += 1
    }
  }
  return num
}

十六进制转为RGB

将十六进制颜色值转换为 RGB 格式。

ts 复制代码
/**
 * Converts a hex color code to an RGB format.
 * 
 * @param hex The hex color code to convert.
 * @returns The RGB representation of the color.
 */
function hex2Rgb(hex) { // 十六进制转为RGB
    let rgb = []; // 定义rgb数组
    if (/^\#[0-9A-F]{3}$/i.test(hex)) { // 判断是否为3位十六进制数
        let sixHex = '#';
        hex.replace(/[0-9A-F]/ig, function(kw) {
            sixHex += kw + kw; // 转换为六位
        });
        hex = sixHex; // 保存回hex
    }
    if (/^#[0-9A-F]{6}$/i.test(hex)) { // 判断是否为六位十六进制数
        hex.replace(/[0-9A-F]{2}/ig, function(kw) {
            rgb.push(parseInt(kw,16)); // 转换为十进制
        });
        return `rgb(${rgb.join(',')})`; // 输出RGB
    } else {
        console.log(`Input ${hex} is wrong!`);
        return 'rgb(0,0,0)';
    }
}

RGB转为十六进制

将 RGB 颜色值转换为十六进制格式。

ts 复制代码
/**
 * Converts an RGB color to a hex code.
 * 
 * @param rgb The RGB color to convert.
 * @returns The hex representation of the color.
 */
function rgb2Hex(rgb) {
    if (/^rgb\((\d{1,3}\,){2}\d{1,3}\)$/i.test(rgb)) { // Test for RGB format
        let hex = '#';
        rgb.replace(/\d{1,3}/g, function(kw) { // Extract RGB values
            kw = parseInt(kw).toString(16); // Convert to hex
            kw = kw.length < 2 ? 0 + kw : kw; // Ensure two digits
            hex += kw;
        });
        return hex;
    } else {
        console.log(`Input ${rgb} is wrong!`);
        return '#000'; // Return #000 for invalid input
    }
}

生成随机颜色-十六进制格式

生成一个随机的十六进制颜色值。

ts 复制代码
/**
 * Generates a random color in hex format.
 * 
 * @returns A random hex color code.
 */
function randomHexColor() {
    return '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).substr(-6);
}

生成随机颜色-RGB格式

生成一个随机的 RGB 颜色值。

ts 复制代码
/**
 * Generates a random color in RGB format.
 * 
 * @returns A random RGB color.
 */
function randomRgbColor() { // 随机生成RGB颜色
    const r = Math.floor(Math.random() * 256); // Random r value
    const g = Math.floor(Math.random() * 256); // Random g value
    const b = Math.floor(Math.random() * 256); // Random b value
    return `rgb(${r},${g},${b})`; // Return RGB color
}

生成随机颜色-RGBA格式

生成一个随机的 RGBA 颜色值。

ts 复制代码
/**
 * Generates a random color in RGBA format.
 * 
 * @returns A random RGBA color with an alpha value.
 */
function randomRgbaColor() { // 随机生成RGBA颜色
    const r = Math.floor(Math.random() * 256); // Random r value
    const g = Math.floor(Math.random() * 256); // Random g value
    const b = Math.floor(Math.random() * 256); // Random b value
    const alpha = Math.random(); // Random alpha value
    return `rgb(${r},${g},${b},${alpha})`; // Return RGBA color
}

数组去重 unique

去除数组中的重复元素,返回一个新的数组。

ts 复制代码
/**
 * Removes duplicate values from an array.
 * 
 * @param arr The array to remove duplicates from.
 * @returns A new array with unique values.
 */
const unique = <T extends any>(arr: T[]): T[] => {
  return [...new Set(arr)];
};

生成随机不重复 ID(1)

生成随机 ID,包含字母和数字。

ts 复制代码
const urlAlphabet =
  'useandom26T198340PX75pxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrictil1b'

/**
 * Generates a random unique ID.
 * 
 * @param size The length of the ID.
 * @returns A random unique ID.
 */
const nanoid = (size = 21) => {
  let id = '';
  let i = size;
  while (i--) {
    id += urlAlphabet[(Math.random() * 66) | 0];
  }
  return id;
}

生成随机不重复 ID(2)

生成一个基于当前时间戳和随机数的唯一 ID。

ts 复制代码
/**
 * Generates a random unique ID based on the current timestamp and random values.
 * 
 * @returns A random unique ID.
 */
export const generateUniqueId = () => Date.now().toString(36) + Math.random().toString(36).slice(2);

快速生成自然数数组

生成一个包含从 0 开始的自然数数组的不同的实现方式。

ts 复制代码
const n = 10000;

// 方法一 快
let i = 0;
new Array(n).fill(i++);

// 方法二 最慢
Array.from({ length: n }, (v, i) => i);

// 方法三 慢
[...Array(n).keys()];
 
// lodash 快
 _.times(n);

数组打乱,随机排序

打乱数组的顺序,进行随机排序。

ts 复制代码
arr.sort(() => Math.random() - 0.5);

isValidUrl

判断给定的字符串是否为有效的 URL。

ts 复制代码
function isValidUrl(url: string) {
  try {
    new URL(url);
    return true; // 格式正确
  } catch (e) {
    return false; // 格式错误
  }
}
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
ElasticPDF-新国产PDF编辑器13 分钟前
Vue PDF Annotation plugin library online API examples
javascript·vue.js·pdf
鱼樱前端15 分钟前
Vite 工程化深度解析与最佳实践
前端·javascript
鱼樱前端22 分钟前
Webpack 在前端工程化中的核心应用解析-构建老大
前端·javascript
Moment22 分钟前
多人协同编辑算法 —— CRDT 算法 🐂🐂🐂
前端·javascript·面试
小付同学呀27 分钟前
前端快速入门学习4——CSS盒子模型、浮动、定位
前端·css·学习
ElasticPDF-新国产PDF编辑器2 小时前
Vue 项目使用 pdf.js 及 Elasticpdf 教程
javascript·vue.js·pdf
OpenTiny社区2 小时前
TinyPro 中后台管理系统使用指南——让页面搭建变得如此简单!
前端·vue.js·开源
我有一只臭臭2 小时前
webpack配置解析
前端·webpack
我有一只臭臭2 小时前
Vue中webpack的使用
前端·vue.js·webpack