实用篇:JS工具函数,提高生产力的利器,助力高效开发(一)

原文地址:实用篇:JS工具函数,提高生产力的利器,助力高效开发(一)

在这篇文章中,我们将探讨JavaScript中的工具函数。这些函数是用来解决日常开发中常见问题的实用代码。它们可以极大地提高开发效率和代码质量。

在JavaScript开发过程中,我们经常遇到一些通用的任务,比如处理数组、对象、日期、字符串等。如果每次遇到这些问题,我们都从头开始编写代码,那么开发效率会大大降低。工具函数就是用来解决这些常见问题的。它们提供了一种重用代码的方式,让我们能够更快地完成任务,同时保持代码的清晰和可维护。当然,我们我们也可以使用第三方库,比如lodash是一个非常流行的JavaScript工具库,它提供了许多实用的工具函数。

01数字千分位分割

1、使用正则表达式和replace函数

const numFormat = (num) => {
  const str = num.toString();
  const res = str.replace(/\d+/, function(n) { 
      // 先提取整数部分
      return n.replace(/(\d)(?=(\d{3})+$)/g, function($1) {
          return $1 + ",";
      });
  })
  return res;
}

console.log(numFormat(1649966)) // 1,649,966
console.log(numFormat(673439.6328)); // 673,439.6328
console.log(numFormat(12345.36)) // 12,345.36

2、除法+求模

const numFormat = (num) => {
  let n = num;
  let r = '';
  let temp = '';
  do {
    // 求模的值, 用于获取高三位,这里可能有小数
    mod = n % 1000;
    // 值是不是大于1,是继续的条件
    n = n / 1000;
    // 高三位
    temp = ~~mod;
    // 1.填充: n > 1 循环未结束, 就要填充为比如 1 => 001
    // 不然temp = ~~mod的时候, 1 001, 就会变成 "11"
    // 2.拼接“,”
    r = (n >= 1 ? `${temp}`.padStart(3, '0') : temp) + (!!r ? ',' + r : '');
  } while (n >= 1);
  const strNumber = num + '';
  let index = strNumber.indexOf('.');
  // 拼接小数部分
  if (index >= 0) {
    r += strNumber.substring(index);
  }
  return r;
}

console.log(numFormat(1649966)) // 1,649,966
console.log(numFormat(673439.6328)); // 673,439.6328
console.log(numFormat(12345.36)) // 12,345.36

3、数组分割法

const numFormat = (num) => {
  // 转为字符串,并按照.拆分
  const arr = (num + '').split('.');
  // 整数部分再拆分
  const int = arr[0].split('');
  // 小数部分
  const fraction = arr[1] || '';
  // 返回的变量
  let r = '';
  int.reverse().forEach(function (v, i) {
      // 非第一位并且是位值是3的倍数,添加“,”
      if (i !== 0 && i % 3 === 0) {
          r = v + ',' + r;
      } else {
          // 正常添加字符(这是好写法)
          r = v + r;
      }
  });
  // 整数部分和小数部分拼接
  return r + (!!fraction ? '.' + fraction : '');
}

console.log(numFormat(1649966)) // 1,649,966
console.log(numFormat(673439.6328)); // 673,439.6328
console.log(numFormat(12345.36)) // 12,345.36

02生成指定范围随机数

const randomNum = (min, max) => Math.floor(Math.random() * (max - min    + 1)) + min;

03字符串首字母大写

const fistLetterUpper = (str) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
};

console.log(fistLetterUpper('hello word'))

04每个单词首字母大写

const everyLetterUpper = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());

console.log(everyLetterUpper('hello world! today is a wonderful day'));
// Hello World! Today Is A Wonderful Day

05根据parent_id生成树结构

// pid代表它的父结点
const list =[
  { id: 1,name:"部门1", pid: 0 },
  { id: 2, name:"部门2", pid:1 },
  { id: 3,name:"部门3", pid: 1 },
  { id: 4,name:"部门4", pid: 3 },
  { id: 5,name:"部门5", pid: 4 }
]
//希望输出的结果
const resultList = [
  {
    id: 1,
    name: "部门1",
    pid: 0,
    children: [
      {
        id: 2,
        name: "部门2",
        pid: 1,
        children: []
      },
      {
        id: 3,
        name: "部门3",
        pid: 1,
        children: [
            // ...
        ]
      }
    ]
  }
]

1、Map对象实现

const listToTree = (list) => {
  //最终树形结构的结果
  const result = [];
  const itemMap = {};
  for (const item of list) {
    const id = item.id;
    const pid = item.pid;
    if (!itemMap[id]) {
      itemMap[id] = {
          children: [],
      }
    }
    itemMap[id] = {
      ...item,
      children: itemMap[id]["children"]
    }
    const treeItem = itemMap[id];
    if (pid === 0) {
      result.push(treeItem);
    } else {
      if (!itemMap[pid]) {
        itemMap[pid] = {
          children: [],
        }
      }
      itemMap[pid].children.push(treeItem);
    }
  }
  return result;
}
listToTree(list);

2、递归实现

//递归查找获取子节点
// List扁平数组
// 树形结构最终数据
// 父节点
const childGet = (list, result, pid) => {
  for (const item of list) {
    if (item.pid === pid) {
      const newItem = { ...item, children: [] };
      result.push(newItem);
      childGet(list, newItem.children, item.id);
    }
  }
}
// 调用实现
const listToTree = (list, pid) => {
  const result = [];
  childGet(list, result, pid);
  return result;
};
listToTree(list, 0);

3、filter+递归(方法2进阶版)

const listToTree = (list, id, pid='pid') => {
  const items = list.filter(item => item[pid] === id);
  const result = items.map(item => ({ 
    ...item, 
    children: listToTree(list, item.id) 
  }));
  return result;
}

listToTree(list, 0, 'pid')

06对象属性剔除

const omit = (object, props = []) => {
  let res = {};
  Object.keys(object).forEach(key => {
    if (props.includes(key) === false) {
      res[key] = typeof object[key] === 'object' && object[key] !== null ?
        JSON.parse(JSON.stringify(object[key])) :
        object[key]
    }
  })
  return res;
}

const obj = {
  id: '1',
  name: '张三',
  age: 18,
  desc: ''
}
omit(obj, ['age'])
// {id: '1', name: '张三', desc: ''}

07去除字符串两端空格

const trimFn = (value) => {   const str = value.toString();   const reExtraSpace = /^\s*(.*?)\s+$/;   return str.replace(reExtraSpace, "$1"); } trimFn(' 12345678 ') // 12345678

08日期格式化

const formatDate = (format='Y-M-D h:m:s', timestamp=Date.now()) => {
  let date = new Date(timestamp)
  let dateInfo = {
    Y: date.getFullYear(),
    M: date.getMonth()+1,
    D: date.getDate(),
    h: date.getHours(),
    m: date.getMinutes(),
    s: date.getSeconds()
  }
  let formatNumber = (n) => n > 10 ? n : '0' + n
  let res = format
    .replace('Y', dateInfo.Y)
    .replace('M', dateInfo.M)
    .replace('D', dateInfo.D)
    .replace('h', formatNumber(dateInfo.h))
    .replace('m', formatNumber(dateInfo.m))
    .replace('s', formatNumber(dateInfo.s))
  return res
}

formatDate() 
// 2023-11-25 14:26:36
formatDate('Y年M月D日 h时m分s秒') 
// 2023年11月25日 14时26分37秒
formatDate('h:m Y-M-D', 1700919198000) 
// 21:33 2023-11-25

09防抖

/**
 * @param {function} func - 执行函数
 * @param {number} wait - 等待时间
 * @param {boolean} immediate - 是否立即执行
 * @return {function}
 */
const debounce = (func, wait = 300, immediate = false) => {
  let timer, ctx;
  let later = (arg) => setTimeout(()=>{
    func.apply(ctx, arg)
    timer = ctx = null
  }, wait)
  return function(...arg){
    if(!timer){
      timer = later(arg)
      ctx = this
      if(immediate){
        func.apply(ctx, arg)
      }
    }else{
      clearTimeout(timer)
      timer = later(arg)
    }
  }
}

let scrollHandler = debounce(function(e){
  console.log(e)
}, 500)
window.onscroll = scrollHandler

10节流

/**
 * @param {function} func - 执行函数
 * @param {number} delay - 延迟时间
 * @return {function}
 */
const throttle = (func, delay) => {
  let timer = null
  return function(...arg){
    if(!timer){
      timer = setTimeout(()=>{
        func.apply(this, arg)
        timer = null
      }, delay)
    }
  }
}

let scrollHandler = throttle(function(e){
  console.log(e)
}, 500)
window.onscroll = scrollHandler

11base64数据导出文件下载

/**
 * @param {string} filename - 下载时的文件名
 * @param {string} data - base64字符串
 */
const downloadFile = (filename, data) => {
  let downloadLink = document.createElement('a');
  if (downloadLink) {
    document.body.appendChild(downloadLink);
    downloadLink.style = 'display: none';
    downloadLink.download = filename;
    downloadLink.href = data;
    if (document.createEvent) {
      let downloadEvt = document.createEvent('MouseEvents');
      downloadEvt.initEvent('click', true, false);
      downloadLink.dispatchEvent(downloadEvt);
    } else if (document.createEventObject) {
      downloadLink.fireEvent('onclick');
    } else if (typeof downloadLink.onclick == 'function') {
      downloadLink.onclick();
    }
    document.body.removeChild(downloadLink);
  }
}

12检测是否为PC浏览器

const isPCBroswer = () => {  
  let e = window.navigator.userAgent.toLowerCase()  
    , t = "ipad" == e.match(/ipad/i)  
    , i = "iphone" == e.match(/iphone/i)  
    , r = "midp" == e.match(/midp/i)  
    , n = "rv:1.2.3.4" == e.match(/rv:1.2.3.4/i)  
    , a = "ucweb" == e.match(/ucweb/i)  
    , o = "android" == e.match(/android/i)  
    , s = "windows ce" == e.match(/windows ce/i)  
    , l = "windows mobile" == e.match(/windows mobile/i);
  return !(t || i || r || n || a || o || s || l)  
}

13数组中获取随机数

const sample = arr => arr[Math.floor(Math.random() * arr.length)];

14手机号脱敏

const telFormat = (tel) => {
  // 第一种:正则表达式
  const result = tel.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");

  // 第二种:字符串 substring 方法
  /* 利用replace()方法,将电话号码中符合条件的部分替换成 ****,
      条件就是 tel.substring(3,7) 截取的中间四位字符串 */
  const result = tel.replace(tel.substring(3,7), "****");

  // 第三种:字符串substr方法
  // 截取字符串的前三项  + **** + 截取字符串的第七项之后的字符串
  const result = tel.substr(0,3) + "****" + tel.substr(7);
}
telFormat(13612345678) // 136****5678

15驼峰命名转短横线命名

const getKebabCase = (str) => {
  return str.replace(/[A-Z]/g, (item) => '-' + item.toLowerCase())
}
getKebabCase('firstCodeHelloWorld')
// first-code-hello-world

16短横线命名转驼峰命名

const getCamelCase = (str) => {
  return str.replace( /-([a-z])/g, (i, item) => item.toUpperCase())
}
getCamelCase('first-code-hello-world')
// firstCodeHelloWorld

总结

在JavaScript中,工具函数(也称为实用函数或辅助函数)是用来解决日常编程任务的函数。它们通常不是用于实现应用程序的主要功能,而是提供一些实用的功能,使开发人员的工作更加轻松。

本篇文章就先分享到这里,更多精彩内容,您可以关注作者及时获取后续的最新文章内容!文中有错误的地方,欢迎大家批评指正,谢谢您的观看。

你可能感兴趣的:(javascript,开发语言,ecmascript)