JavaScript 实用函数大全(超实用)

98 阅读6分钟

🧪 类型判断类

基本类型判断

const is = {
  isObject: val => val !== null && typeof val === 'object' && !Array.isArray(val),
  isArray: Array.isArray,
  isFunction: val => typeof val === 'function',
  isString: val => typeof val === 'string',
  isNumber: val => typeof val === 'number' && !isNaN(val),
  isBoolean: val => typeof val === 'boolean',
  isNull: val => val === null,
  isUndefined: val => typeof val === 'undefined',
  isEmpty: val => val == null || (typeof val === 'object' && Object.keys(val).length === 0),
};

结构类型判断

Object.assign(is, {
  isObject: val => val !== null && typeof val === 'object' && !Array.isArray(val),
  isArray: Array.isArray,
  isFunction: val => typeof val === 'function',
  isDate: val => Object.prototype.toString.call(val) === '[object Date]',
  isRegExp: val => Object.prototype.toString.call(val) === '[object RegExp]',
  isMap: val => Object.prototype.toString.call(val) === '[object Map]',
  isSet: val => Object.prototype.toString.call(val) === '[object Set]',
  isWeakMap: val => Object.prototype.toString.call(val) === '[object WeakMap]',
  isWeakSet: val => Object.prototype.toString.call(val) === '[object WeakSet]',
});

特殊对象判断

Object.assign(is, {
  isPromise: val => !!val && typeof val.then === 'function' && typeof val.catch === 'function',
  isAsyncFunction: val => Object.prototype.toString.call(val) === '[object AsyncFunction]',
  isGeneratorFunction: val => Object.prototype.toString.call(val) === '[object GeneratorFunction]',
  isError: val => val instanceof Error || Object.prototype.toString.call(val) === '[object Error]',
  isNaN: val => Number.isNaN(val),
});

浏览器/DOM 环境判断

Object.assign(is, {
  isWindow: val => typeof window !== 'undefined' && val === window,
  isElement: val => typeof Element !== 'undefined' && val instanceof Element,
  isNode: val => typeof Node !== 'undefined' && val instanceof Node,
  isEvent: val => val instanceof Event,
});

🧮 数字相关

生成指定范围浮点数

function getRandomFloat(min, max, digits = 2) {
  const rand = Math.random() * (max - min) + min;
  return parseFloat(rand.toFixed(digits));
}

随机取样数组中的值

function getRandomItem(arr) {
  return arr[Math.floor(Math.random() * arr.length)];
}

生成随机整数(包含 min 和 max)

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

保留指定小数点

function toFixed(num, decimals = 2) {
  return Number(num.toFixed(decimals));
}

获取范围内随机浮点数

function getRandomFloat(min, max, decimals = 2) {
  return parseFloat((Math.random() * (max - min) + min).toFixed(decimals));
}

千分位格式化(1234567.89 => 1,234,567.89)

function formatThousands(num) {
  return Number(num).toLocaleString('en-US');
}

自定义小数位(四舍五入)

function toFixed(num, decimals = 2) {
  return parseFloat(Number(num).toFixed(decimals));
}

数字前补零(比如序号 0005)

function padZero(num, length = 2) {
  return String(num).padStart(length, '0');
}

百分比格式(0.75 => "75.00%")

function toPercent(num, digits = 2) {
  return (num * 100).toFixed(digits) + '%';
}

是否有效数字

function isValidNumber(val) {
  return typeof val === 'number' && !isNaN(val) && isFinite(val);
}

判断是否为整数

function isInteger(num) {
  return Number.isInteger(num);
}

判断是否为偶数/奇数

function isEven(num) {
  return num % 2 === 0;
}
function isOdd(num) {
  return num % 2 !== 0;
}

判断是否在范围内

function isInRange(num, min, max) {
  return num >= min && num <= max;
}

平均值

function average(arr) {
  const sum = arr.reduce((acc, n) => acc + n, 0);
  return arr.length ? sum / arr.length : 0;
}

求和

function sum(arr) {
  return arr.reduce((acc, n) => acc + n, 0);
}

最大值 / 最小值

function max(arr) {
  return Math.max(...arr);
}
function min(arr) {
  return Math.min(...arr);
}

保证值在区间范围内

function clamp(val, min, max) {
  return Math.min(Math.max(val, min), max);
}

十进制转任意进制

function decToBase(num, base = 16) {
  return Number(num).toString(base);
}

任意进制转十进制

function baseToDec(str, base = 16) {
  return parseInt(str, base);
}

判断是否为浮点数

function isFloat(num) {
  return Number(num) === num && num % 1 !== 0;
}

保留有效数字(科学计数法避免精度丢失)

function toPrecision(num, precision = 6) {
  return Number.parseFloat(Number(num).toPrecision(precision));
}

🧱 数组处理

去重(简单值)

function unique(arr) {
  return [...new Set(arr)];
}

去重(对象数组,基于字段)

function uniqueBy(arr, key) {
  const map = new Map();
  arr.forEach(item => map.set(item[key], item));
  return Array.from(map.values());
}

扁平化(无限深度)

function flatten(arr) {
  return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val), []);
}

扁平化(指定深度)

function flattenDepth(arr, depth = 1) {
  return arr.flat(depth);
}

获取数组中最常出现的元素

function mostFrequent(arr) {
  const freqMap = {};
  let max = 0;
  let result = null;
  arr.forEach(val => {
    freqMap[val] = (freqMap[val] || 0) + 1;
    if (freqMap[val] > max) {
      max = freqMap[val];
      result = val;
    }
  });
  return result;
}

获取重复元素

function findDuplicates(arr) {
  const seen = new Set();
  return arr.filter((item, idx) => {
    if (seen.has(item)) return true;
    seen.add(item);
    return false;
  });
}

数组分块(chunk)

function chunk(arr, size) {
  return Array.from({ length: Math.ceil(arr.length / size) }, (_, i) =>
    arr.slice(i * size, i * size + size)
  );
}

数组交错打散(zip / unzip)

function zip(...arrays) {
  return arrays[0].map((_, i) => arrays.map(arr => arr[i]));
}

function unzip(arr) {
  return arr[0].map((_, i) => arr.map(row => row[i]));
}

洗牌打乱顺序(Fisher-Yates)

function shuffle(arr) {
  const copy = [...arr];
  for (let i = copy.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [copy[i], copy[j]] = [copy[j], copy[i]];
  }
  return copy;
}

排序(数字升序)

function sortAsc(arr) {
  return [...arr].sort((a, b) => a - b);
}

排序(数字降序)

function sortDesc(arr) {
  return [...arr].sort((a, b) => b - a);
}

数组浅对比

function isArrayEqual(a, b) {
  return a.length === b.length && a.every((v, i) => v === b[i]);
}

数组差集

function difference(arr1, arr2) {
  return arr1.filter(item => !arr2.includes(item));
}

数组交集

function intersection(arr1, arr2) {
  return arr1.filter(item => arr2.includes(item));
}

数组合并去重

function union(arr1, arr2) {
  return [...new Set([...arr1, ...arr2])];
}

获取第一个元素

function first(arr) {
  return arr[0];
}

获取最后一个元素

function last(arr) {
  return arr[arr.length - 1];
}

取前 N 项

function take(arr, n = 1) {
  return arr.slice(0, n);
}

删除 falsy 值(false、0、null、undefined、'')

function compact(arr) {
  return arr.filter(Boolean);
}

分组 groupBy:groupBy(users, 'role')

function groupBy(arr, key) {
  return arr.reduce((acc, item) => {
    const groupKey = item[key];
    if (!acc[groupKey]) acc[groupKey] = [];
    acc[groupKey].push(item);
    return acc;
  }, {});
}

创建数组范围(range)

function range(start, end, step = 1) {
  const result = [];
  for (let i = start; i <= end; i += step) {
    result.push(i);
  }
  return result;
}

按条件删除元素(非原地)

function removeBy(arr, predicate) {
  return arr.filter(item => !predicate(item));
}

📜 字符串工具

首字母大写

function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

首字母小写

function unCapitalize(str) {
  return str.charAt(0).toLowerCase() + str.slice(1);
}

去除首尾空格(安全)

function trim(str) {
  return str?.trim?.() ?? '';
}

多空格转单空格并去首尾

function cleanSpace(str) {
  return str.replace(/\s+/g, ' ').trim();
}

转为驼峰(my-name => myName)

function toCamelCase(str) {
  return str.replace(/[-_](\w)/g, (_, c) => c.toUpperCase());
}

转为下划线风格(myName => my_name)

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

转为短横线风格(myName => my-name)

function toKebabCase(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}

驼峰转空格(helloWorld => hello world)

function camelToWords(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase();
}

Base64 编码

function encodeBase64(str) {
  return btoa(unescape(encodeURIComponent(str)));
}

Base64 解码

function decodeBase64(str) {
  return decodeURIComponent(escape(atob(str)));
}

HTML 转义(防止 XSS)

function escapeHTML(str) {
  const map = { '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', "'": '&#039;' };
  return str.replace(/[<>&"']/g, m => map[m]);
}

HTML 反转义

function unescapeHTML(str) {
  const map = { '&lt;': '<', '&gt;': '>', '&amp;': '&', '&quot;': '"', '&#039;': "'" };
  return str.replace(/&(lt|gt|amp|quot|#039);/g, m => map[m]);
}

字符串模板替换("Hi, {{name}}", {name: "Levi"})

function template(str, data = {}) {
  return str.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] ?? '');
}

左右补全到指定长度

function padStart(str, length, char = '0') {
  return str.padStart(length, char);
}

function padEnd(str, length, char = ' ') {
  return str.padEnd(length, char);
}

字符串脱敏:maskString("13812345678", 3, 4) => "138****5678"

function maskString(str, start = 3, end = 4) {
  return str.slice(0, start) + '*'.repeat(str.length - start - end) + str.slice(-end);
}

限制最大长度,超出截断并添加省略号

function ellipsis(str, max = 10) {
  return str.length > max ? str.slice(0, max) + '…' : str;
}

判断是否是空字符串(或纯空白)

function isBlank(str) {
  return !str || /^\s*$/.test(str);
}

判断是否为有效 URL

function isURL(str) {
  try {
    new URL(str);
    return true;
  } catch {
    return false;
  }
}

判断是否为邮箱

function isEmail(str) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str);
}

判断是否为手机号(中国)

function isMobile(str) {
  return /^1[3-9]\d{9}$/.test(str);
}

字符串反转

function reverse(str) {
  return str.split('').reverse().join('');
}

获取字符出现次数

function countOccurrences(str, char) {
  return str.split(char).length - 1;
}

🌐 浏览器/DOM 工具

简易选择器(返回单个元素)

function $(selector, context = document) {
  return context.querySelector(selector);
}

简易选择器(返回元素数组)

function $$(selector, context = document) {
  return Array.from(context.querySelectorAll(selector));
}

遍历元素数组

function forEachElem(selector, fn, context = document) {
  $$(selector, context).forEach(fn);
}

添加事件监听

function on(elem, event, handler, options) {
  elem.addEventListener(event, handler, options);
}

移除事件监听

function off(elem, event, handler, options) {
  elem.removeEventListener(event, handler, options);
}

委托事件(事件代理)

function delegate(parent, selector, event, handler) {
  function delegatedHandler(e) {
    const target = e.target.closest(selector);
    if (target && parent.contains(target)) {
      handler.call(target, e);
    }
  }
  parent.addEventListener(event, delegatedHandler);
  return () => parent.removeEventListener(event, delegatedHandler);
}

获取元素计算样式

function getStyle(elem, prop) {
  return getComputedStyle(elem).getPropertyValue(prop);
}

设置单个样式

function setStyle(elem, prop, value) {
  elem.style[prop] = value;
}

批量设置样式

function setStyles(elem, styles = {}) {
  Object.entries(styles).forEach(([prop, value]) => {
    elem.style[prop] = value;
  });
}

判断元素是否包含某个类

function hasClass(elem, className) {
  return elem.classList.contains(className);
}

添加类

function addClass(elem, className) {
  elem.classList.add(className);
}

移除类

function removeClass(elem, className) {
  elem.classList.remove(className);
}

切换类

function toggleClass(elem, className, force) {
  elem.classList.toggle(className, force);
}

获取元素文本内容

function getText(elem) {
  return elem.textContent;
}

设置元素文本内容

function setText(elem, text) {
  elem.textContent = text;
}

获取元素尺寸和位置信息

function getRect(elem) {
  return elem.getBoundingClientRect();
}

判断元素是否在视口内(完全可见)

function isInViewport(elem) {
  const rect = getRect(elem);
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
}

判断元素是否部分可见

function isPartiallyInViewport(elem) {
  const rect = getRect(elem);
  const windowHeight = window.innerHeight || document.documentElement.clientHeight;
  const windowWidth = window.innerWidth || document.documentElement.clientWidth;

  return (
    rect.bottom > 0 &&
    rect.right > 0 &&
    rect.top < windowHeight &&
    rect.left < windowWidth
  );
}

滚动到元素(平滑滚动)

function scrollToElem(elem, options = { behavior: 'smooth', block: 'start' }) {
  elem.scrollIntoView(options);
}

获取当前滚动位置

function getScrollPosition() {
  return {
    x: window.pageXOffset || document.documentElement.scrollLeft,
    y: window.pageYOffset || document.documentElement.scrollTop
  };
}

滚动到顶部

function scrollToTop(behavior = 'smooth') {
  window.scrollTo({ top: 0, behavior });
}

判断是否是移动端

function isMobile() {
  return /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
}

判断是否支持某个CSS属性(标准写法)

function supportsCssProperty(prop) {
  return prop in document.body.style;
}

获取当前浏览器语言

function getBrowserLanguage() {
  return navigator.language || navigator.userLanguage;
}

Cookie 操作

function setCookie(name, value, days = 7, path = '/') {
  const expires = new Date(Date.now() + days * 864e5).toUTCString();
  document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=${path}`;
}

function getCookie(name) {
  return document.cookie.split('; ').reduce((r, v) => {
    const parts = v.split('=');
    return parts[0] === name ? decodeURIComponent(parts[1]) : r;
  }, '');
}

function deleteCookie(name, path = '/') {
  setCookie(name, '', -1, path);
}

localStorage / sessionStorage 操作

function setLocalStorage(key, value) {
  localStorage.setItem(key, JSON.stringify(value));
}

function getLocalStorage(key) {
  const value = localStorage.getItem(key);
  try {
    return JSON.parse(value);
  } catch {
    return value;
  }
}

function removeLocalStorage(key) {
  localStorage.removeItem(key);
}

function clearLocalStorage() {
  localStorage.clear();
}

🔁 异步与控制流

等待直到条件成立(轮询)

function waitUntil(conditionFn, interval = 100, timeout = 5000) {
  return new Promise((resolve, reject) => {
    const start = Date.now();
    const timer = setInterval(() => {
      if (conditionFn()) {
        clearInterval(timer);
        resolve();
      } else if (Date.now() - start > timeout) {
        clearInterval(timer);
        reject(new Error("waitUntil timeout"));
      }
    }, interval);
  });
}

重试函数(带次数和延时)

async function retry(fn, retries = 3, delay = 500) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fn();
    } catch (e) {
      if (i === retries - 1) throw e;
      await sleep(delay);
    }
  }
}

🧩 其他工具函数

格式化日期:date为Date对象或时间戳,fmt格式如 'yyyy-MM-dd hh:mm:ss'

function formatDate(date, fmt = 'yyyy-MM-dd hh:mm:ss') {
  if (!date) return '';
  date = date instanceof Date ? date : new Date(date);
  const o = {
    'M+': date.getMonth() + 1
    'd+': date.getDate(),
    'h+': date.getHours(), 
    'm+': date.getMinutes(),
    's+': date.getSeconds(),
    'q+': Math.floor((date.getMonth() + 3) / 3),
    'S': date.getMilliseconds()
  };
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  }
  for (const k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).slice(('' + o[k]).length));
    }
  }
  return fmt;
}

获取两个日期间隔天数

function daysBetween(date1, date2) {
  const diff = Math.abs(new Date(date1) - new Date(date2));
  return Math.floor(diff / (24 * 3600 * 1000));
}

深拷贝

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (hash.has(obj)) return hash.get(obj);
  let clone;
  if (Array.isArray(obj)) clone = [];
  else if (obj instanceof Date) clone = new Date(obj);
  else if (obj instanceof RegExp) clone = new RegExp(obj);
  else clone = Object.create(Object.getPrototypeOf(obj));
  hash.set(obj, clone);
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], hash);
    }
  }
  return clone;
}

防抖函数:事件停止触发后延迟执行

function debounce(fn, wait = 300) {
  let timer = null;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), wait);
  };
}

节流函数:事件触发间隔控制

function throttle(fn, wait = 300) {
  let lastTime = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastTime >= wait) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

获取 URL 参数对象

function getUrlParams(url = window.location.href) {
  const params = {};
  const parser = new URL(url);
  for (const [key, value] of parser.searchParams.entries()) {
    params[key] = value;
  }
  return params;
}

将对象转为 URL 参数字符串

function toQueryString(params = {}) {
  return Object.entries(params)
    .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
    .join('&');
}

转数组(非数组则包裹为单元素数组)

function toArray(val) {
  return Array.isArray(val) ? val : [val];
}

安全转数字,失败返回默认值

function toNumber(val, def = 0) {
  const num = Number(val);
  return isNaN(num) ? def : num;
}

对象深度合并

function deepMerge(target = {}, ...sources) {
  sources.forEach(source => {
    if (typeof source !== 'object' || source === null) return;
    Object.keys(source).forEach(key => {
      const val = source[key];
      if (Array.isArray(val)) {
        target[key] = val.slice();
      } else if (typeof val === 'object' && val !== null) {
        if (!target[key] || typeof target[key] !== 'object') target[key] = {};
        deepMerge(target[key], val);
      } else {
        target[key] = val;
      }
    });
  });
  return target;
}

版本号比较(比如 '1.2.10' 和 '1.2.9')

function compareVersion(v1, v2) {
  const a1 = v1.split('.').map(Number);
  const a2 = v2.split('.').map(Number);
  const len = Math.max(a1.length, a2.length);
  for (let i = 0; i < len; i++) {
    const n1 = a1[i] || 0;
    const n2 = a2[i] || 0;
    if (n1 > n2) return 1;
    if (n1 < n2) return -1;
  }
  return 0;
}

生成随机字符串(默认长度8)

function randomString(len = 8) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let str = '';
  for (let i=0; i<len; i++) {
    str += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return str;
}

判断是否为 JSON 字符串

function isJsonString(str) {
  if (typeof str !== 'string') return false;
  try {
    const obj = JSON.parse(str);
    return obj && typeof obj === 'object';
  } catch {
    return false;
  }
}

📁 文件工具

读取文件为 base64

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = e => reject(e);
    reader.readAsDataURL(file);
  });
}

文件转文本(适合 txt / json / csv)

function fileToText(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsText(file);
  });
}

文件转 ArrayBuffer(适合音频、视频等)

function fileToArrayBuffer(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
}

文件转 JSON(含异常处理)

async function fileToJson(file) {
  const text = await fileToText(file);
  try {
    return JSON.parse(text);
  } catch (e) {
    throw new Error('JSON 格式错误');
  }
}

base64 → Blob

function base64ToBlob(base64, mime = '') {
  const byteString = atob(base64.split(',')[1]);
  const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(ab);
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ab], { type: mime });
}

Blob → File

function blobToFile(blob, fileName) {
  return new File([blob], fileName, { type: blob.type });
}

Blob → base64

function blobToBase64(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

获取文件扩展名

function getFileExtension(filename) {
  return filename.split('.').pop().toLowerCase();
}

判断文件类型(图片、视频等)

function isImage(file) {
  return file.type.startsWith('image/');
}

function isVideo(file) {
  return file.type.startsWith('video/');
}

function isPDF(file) {
  return file.type === 'application/pdf';
}

判断文件大小是否超限(单位:MB)

function isFileTooLarge(file, maxMB) {
  return file.size / 1024 / 1024 > maxMB;
}

获取图片尺寸(File 或 URL)

function getImageSizeFromFile(file) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    fileToBase64(file).then(src => {
      img.onload = () => resolve({ width: img.width, height: img.height });
      img.onerror = reject;
      img.src = src;
    });
  });
}

压缩图片(使用 Canvas)

function compressImage(file, quality = 0.8, type = 'image/jpeg') {
  return new Promise((resolve, reject) => {
    const img = new Image();
    fileToBase64(file).then(base64 => {
      img.onload = () => {
        const canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0);
        canvas.toBlob(blob => {
          if (blob) resolve(blob);
          else reject(new Error('压缩失败'));
        }, type, quality);
      };
      img.onerror = reject;
      img.src = base64;
    });
  });
}

下载文本为文件

function downloadTextFile(filename, content, type = 'text/plain') {
  const blob = new Blob([content], { type });
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  link.download = filename;
  link.click();
  URL.revokeObjectURL(link.href);
}

下载 blob 文件

function downloadBlobFile(blob, filename = 'file') {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

下载远程文件(例如图片 URL)

function downloadByUrl(url, filename = 'download') {
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.target = '_blank';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

分片处理(可用于大文件上传)

function sliceFile(file, chunkSize = 1024 * 1024) {
  const chunks = [];
  let start = 0;
  while (start < file.size) {
    chunks.push(file.slice(start, start + chunkSize));
    start += chunkSize;
  }
  return chunks;
}

合并 Blob 切片

function mergeBlobs(blobParts, type = 'application/octet-stream') {
  return new Blob(blobParts, { type });
}

原文链接

JavaScript 实用函数大全(超实用)