这10个高频工具函数请收藏好,避免重复造轮子

e825f485d396cc5aa8aa3a28b0252512.jpeg

当我们编写JavaScript代码时,常常需要进行各种数据的处理和检查。有时候我们需要验证一个变量是否为函数,有时候需要将RGB值转换为十六进制表示,有时候需要检查一个对象是否为安全对象等等。为了方便开发,我们可以封装一些常用的工具函数来处理这些问题。在这篇文章中,我将介绍10个常用的JavaScript工具函数,它们能帮助我们更快更方便地处理我们日常中遇到业务问题,希望这些整理能够帮助到你,避免重复造轮子。

1、滚动到顶部

// 声明 scrollTopH 变量用于存储当前页面滚动位置
let scrollTopH = { value: window.pageYOffset 
                    || document.documentElement.scrollTop 
                    || document.body.scrollTop };
const bindTop = () => {
  // 方法1:可以将窗口滚动到顶部,但效果不太好
  window.scrollTo(0, 0);

  // 将文档元素(即整个页面)的scrollTop属性设置为0,也可以实现将页面滚动到顶部的效果
  document.documentElement.scrollTop = 0;

  // 方法2:通过定时器逐步滚动到顶部,实现更平滑的视觉效果
  // 使用setInterval创建一个定时器,每10毫秒执行一次回调函数
  const timeTop = setInterval(() => {
    // 控制滑动的距离,每次将scrollTop属性减少50
    scrollTopH.value -= 50;
    document.documentElement.scrollTop = scrollTopH.value;

    // 当scrollTop属性的值小于等于0时,说明已经滑动到页面顶部
    if (scrollTopH.value <= 0) {
      // 清除定时器,避免定时器一直运行造成问题
      clearInterval(timeTop);
    }
  }, 10);
};

这段代码定义了一个名为bindTop的函数,其主要功能是滚动页面到顶部。该函数包含两种方法,一种是直接将窗口滚动到顶部,另一种是通过一个定时器逐步滚动到顶部,以达到更平滑的视觉效果。

具体来说,函数的第一部分使用了两种方法将滚动条位置设置为0,以确保页面在顶部。window.scrollTo(0, 0)用于将窗口滚动到顶部,
document.documentElement.scrollTop = 0用于设置文档元素(即整个页面)的scrollTop属性为0。

函数的第二部分使用了一个名为timeTop的定时器,通过逐步减小文档元素的scrollTop属性的值来实现平滑滚动。具体来说,每10毫秒将scrollTop属性的值减少50,直到它小于等于0。一旦到达顶部,定时器将被清除。要注意的是,scrollTopH是一个可能在函数之外定义的变量,其中存储了滚动条的位置。函数不负责初始化此变量,而是假定它已经存在并包含当前滚动条的位置。

最后,要注意在方法2中定时器的清除(*),如果不清除定时器,它会一直运行,直到页面被卸载或刷新。因此,在滚动到顶部后,必须清除定时器以避免出现问题。

2、复制文本内容

const copyText = (text) => {
  // 方法1:尝试使用clipboardData对象将文本复制到剪贴板中
  const clipboardData = window.clipboardData;
  if (clipboardData) { // 如果clipboardData对象存在,说明浏览器支持此方法
    clipboardData.clearData(); // 清除剪贴板中的旧数据
    clipboardData.setData('Text', text); // 将text数据复制到剪贴板中
    return true; // 返回复制成功
  } 
  // 方法2:使用document.execCommand方法将文本复制到剪贴板中
  // 注意,该方法已经被弃用,但仍然有些浏览器支持,使用时要注意兼容性
  else if (document.execCommand) {
    // 创建一个textarea元素,并将需要复制的文本赋值给它
    const el = document.createElement('textarea');
    el.value = text;
    el.setAttribute('readonly', ''); // 设置为只读模式,防止用户误操作
    el.style.position = 'absolute';
    el.style.left = '-9999px'; // 将元素的left设置为-9999px,相当于将其放到屏幕外面
    document.body.appendChild(el); // 将该元素添加到body中
    el.select(); // 选中该元素中的文本
    // 将该元素中的文本复制到剪贴板中
    document.execCommand('copy');
    // 删除该元素
    document.body.removeChild(el);
    return true; // 返回复制成功
  }
  return false; // 复制失败
}

copyText('hello!') // 将 'hello!' 文本复制到剪贴板中,返回 true

该函数用于将指定的文本复制到剪贴板中。它首先尝试使用clipboardData对象将文本复制到剪贴板中,如果该对象存在,说明浏览器支持此方法,直接调用其setData方法将文本复制到剪贴板中。

如果clipboardData对象不存在,该函数则尝试使用document.execCommand方法将文本复制到剪贴板中。该方法已经被弃用,但仍然有些浏览器支持。在该方法中,我们先创建一个textarea元素,并将需要复制的文本赋值给它。然后,将该元素添加到body中,将其left设置为-9999px,相当于将其放到屏幕外面。接着,选中该元素中的文本,调用document.execCommand方法将该元素中的文本复制到剪贴板中,最后再将该元素删除。

注意,这个函数只是尝试复制文本到剪贴板,实际是否成功复制要取决于浏览器是否支持该方法。如果两种复制方式都不支持,则返回false。

3、防抖和节流

防抖:在指定时间内频繁触发事件,只以最后一次触发为准。

节流:在指定时间内频繁触发事件,但只会执行一次。

这两种技术有许多应用场景,比如:

防抖:输入搜索,当用户持续输入内容时,使用防抖来减少请求数量并节省请求资源。

节流:一般用于按钮点击场景。在一秒钟内连续点击10次,将会发起10个请求。通过节流处理,如果在1秒钟内多次点击,它只会被触发一次。

接下来我们通过代码实现下:

// 防抖函数,返回一个函数
const debounce = (func, delay) => {
  let timer
  // 返回一个函数
  return function(...args) {
    // 如果定时器存在,先清除之前的定时器
    if (timer) {
      clearTimeout(timer)
    }
    // 创建新的定时器
    timer = setTimeout(() => {
      // 调用传入的函数并传入参数
      func.apply(this, args)
    }, delay)
  }
}

// 节流函数,返回一个函数
const throttle = (func, delay) => {
  let timer
  // 标记是否正在执行
  let flag = true
  // 返回一个函数
  return function(...args) {
    // 如果正在执行,不做任何处理
    if (!flag) {
      return
    }
    // 如果定时器不存在
    if (!timer) {
      // 设置标记为 false
      flag = false
      // 创建定时器
      timer = setTimeout(() => {
        // 调用传入的函数并传入参数
        func.apply(this, args)
        // 清除定时器
        timer = null
        // 设置标记为 true
        flag = true
      }, delay)
    }
  }
}

debounce函数和throttle函数都是函数节流和函数防抖的实现。

debounce函数接受两个参数:一个函数和一个延迟时间,返回一个新函数。当调用这个新函数时,它会在延迟时间内等待,如果在延迟时间内再次调用,那么之前的定时器将被清除,重新创建一个新的定时器。如果在延迟时间内没有再次调用,则会调用传入的函数并传入相应的参数。

throttle函数也接受两个参数:一个函数和一个延迟时间,返回一个新函数。当调用这个新函数时,它会在延迟时间内等待,如果在延迟时间内再次调用,则不会执行任何操作。当延迟时间结束后,才会执行一次传入的函数并传入相应的参数。与debounce函数不同,throttle函数在执行完函数之后,会将flag标记重新设置为true,以便下次能够再次执行。

4、过滤字符串中的非法字符

function filterCharacter(str){
  // 首先设置一个匹配模式
  let pattern = new RegExp("[`~!@#$^&*()=:”“'。,、?|{}':;'%,\\[\\].<>/?~!@#$……&*()&;—|{ }【】‘;]")
  let resultStr1 = "";
  for (let j= 0; j< str.length; j++) {
    // 主要通过 replace 函数,按照规则将字符替换为空,并最终拼接在 resultStr1 中
    resultStr1 = resultStr1 + str.substr(j, 1).replace(pattern, '');
  }
  // 循环结束后,返回最终结果 resultStr1
  return resultStr1;
}

// 例子
filterCharacter('gyaskjdhy12316789#$%^&!@#1=123,./[') // 输出:gyaskjdhy123167891123

代码的功能就是将输入的字符串中的非法字符都过滤掉,得到一个合法的字符串。在这个函数中,主要的操作是通过正则表达式 pattern 来匹配非法字符,然后使用 replace 函数将非法字符替换成空字符串,并最终拼接在 resultStr1 变量中。循环结束后,将 resultStr1 返回作为最终结果。

5、常用正则判断

// 用于验证名字是否符合规范。规范是指名字必须由2-9个字组成。
    const validateName = (name) => {
      const reg = /^[\u4e00-\u9fa5]{2,9}$/;
      return reg.test(name);
    };
// 用于验证手机号码是否符合规范。规范是指手机号码必须由11位数字组成,且以1开头。
    const validatePhoneNum = (mobile) => {
      const reg = /^1[3,4,5,6,7,8,9]\d{9}$/;
      return reg.test(mobile);
    };
// 用于验证密码是否符合规范。规范是指密码必须由6-18位大小写字母、数字或下划线组成。
    const validatePassword = (password) => {
      const reg = /^[a-zA-Z0-9_]{6,18}$/;
      return reg.test(password);
    };

6、初始化数组

const arrList = Array(6).fill()
    console.log(arrList)// What is printed here is['','','','','','']

这段代码定义了一个名为arrList的变量,它是一个包含6个元素的数组,每个元素都为空字符串。

具体来说,这里使用了ES6中的Array构造函数创建了一个长度为6的空数组,然后调用了fill()方法,将该数组中的每个元素都填充为默认值,即空字符串。

7、将 RGB 转换为十六进制

function getColorFun(r, g, b) {
    // 将 RGB 颜色转换为 16 进制形式的字符串
    // 通过位运算符和 toString 方法实现
    // 1 << 24 表示左移 24 位,等同于 Math.pow(2, 24)
    // r << 16 表示将 r 值左移 16 位,g << 8 和 b 相似
    // 然后将这三个值相加并通过 toString(16) 转换成 16 进制字符串
    // 最后通过 slice(1) 去掉第一位多余的 0,得到形如 #b2e837 的颜色字符串
    return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}

getColorFun(178, 232, 55); // 这里的输出是 #b2e837

该函数的作用是将 RGB 颜色值转换为对应的 16 进制颜色字符串,如 (178, 232, 55) 对应的颜色字符串为 "#b2e837"。函数内部使用了位运算符和 toString 方法来实现这一转换。

8、检查是否是函数

const isFunction = (obj) => {
    // 判断对象类型是否为函数,且排除掉可能的 DOM 节点和类数组对象
    return typeof obj === "function" && 
      typeof obj.nodeType !== "number" && 
      typeof obj.item !== "function";
};
  • const isFunction = (obj) => { ... }:定义一个名为 isFunction 的箭头函数,该函数接收一个参数 obj,用于判断其是否为函数类型。

  • return typeof obj === "function" && typeof obj.nodeType !== "number" && typeof obj.item !== "function";:返回一个布尔值,表示该对象是否为函数。该语句首先判断对象类型是否为函数,若是函数,则继续判断是否为 DOM 节点或类数组对象。

typeof obj === "function":判断对象类型是否为函数;

typeof obj.nodeType !== "number":排除可能是 DOM 节点的情况,因为 DOM 节点有 nodeType 属性,而其值是一个数字类型;

typeof obj.item !== "function":排除可能是类数组对象的情况,因为类数组对象一般都有 item 方法。

使用该函数时,只需要传入一个对象参数,即可判断该对象是否为函数类型。例如:

isFunction(()=>{console.log("Hello, World!")}); // true
isFunction(document.querySelector("div")); // false

延伸阅读:类数组对象

类数组对象一般是指具有数组特性,但不是标准数组的对象。这种对象通常拥有一些类数组对象的特性,比如具有 length 属性,可以通过下标访问元素等。

举个例子,arguments 就是一个类数组对象,它的 item 方法返回与指定索引对应的值。下面是一个示例:

function foo() {
  console.log(arguments.item(0));
  console.log(arguments.item(1));
  console.log(arguments.item(2));
}

foo(1, 'hello', true);

上面代码中,arguments 对象就是一个类数组对象,它的 item 方法可以用来访问传递给函数 foo 的参数。在这个例子中,arguments.item(0) 返回的是 1,arguments.item(1) 返回的是 'hello',arguments.item(2) 返回的是 true。

9、检查数组是否安全

const safeArray = (array) => {
  // 判断是否为安全数组,是则返回原数组,否则返回一个空数组
  return Array.isArray(array) ? array : [];
};

这个函数主要是用来检查一个数组是否为安全数组。所谓安全数组是指在当前的 JavaScript 引擎中,可以安全使用数组方法的数组。如果传入的数组不是安全数组,则该函数会返回一个空数组。

函数中主要使用了 Array.isArray() 方法来判断传入的数组是否为数组类型,如果是,则直接返回该数组,否则返回一个空数组。这个方法的作用就是用来判断一个值是否为数组类型,它会返回一个布尔值。

因为在 JavaScript 中,有些对象看起来像数组,但它们不是安全数组,如类数组对象。这些对象具有类似于数组的 length 属性和从 0 开始的数字键,但它们没有数组方法,例如 push() 和 pop()。如果对这些对象使用数组方法,则可能会引发异常。

因此,在使用数组方法之前,我们通常需要先判断该对象是否为安全数组,以确保程序的正常运行。

10、检查对象是否安全

// 判断一个对象是否为有效对象
const isVaildObject = (obj) => {
    return typeof obj === 'object' && 
      !Array.isArray(obj) && 
      Object.keys(obj).length;
    // 如果对象的类型是 "object"、不是数组,并且拥有属性,则认为是有效对象
}

// 返回一个安全的对象
const safeObject = obj => isVaildObject(obj) ? obj : {};
// 如果 obj 是有效对象,返回 obj,否则返回一个空对象{}

函数首先调用了 isVaildObject 函数来判断传入的参数 obj 是否为有效对象。这里的有效对象指的是非数组类型的对象且拥有属性。如果是有效对象,则返回 obj,否则返回一个空对象 {}。

结束

当我们在编写 JavaScript 代码时,经常需要处理各种数据类型。然而,由于 JavaScript 的灵活性,我们经常会遇到数据类型不符合要求的情况,这可能会导致代码运行出错。因此,在处理数据时,我们需要进行一些类型检查和数据过滤,以确保代码的正确性和可靠性。

在本文中,我们介绍了一些 JavaScript 常用的数据处理方法,包括字符串过滤、数组对象判断、颜色值生成、函数判断以及数据安全处理等。这些方法能够帮助我们更方便地处理数据,减少代码出错的概率,提高代码的可读性和可维护性。

当然,这里介绍的方法只是冰山一角,随着 JavaScript 的发展,我们可以使用更多更强大的方法来处理各种数据。因此,在编写代码时,我们需要不断学习新的方法和技术,以便更好地应对各种情况,提高代码的质量和效率。

今天的分享就到这里,希望对你有所帮助,感谢你的阅读,文章创作不易,如果你喜欢我的分享,别忘了点赞转发,让更多有需要的人看到,最后别忘记关注「前端达人」,你的支持将是我分享最大的动力,后续我会持续输出更多内容,敬请期待。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值