文章摘自269个工具函数库:269个工具函数库下

128.blob转file

  1. /**
  2. * @param { blob } blob
  3. * @param { string } fileName
  4. */
  5. export const blobToFile = (blob, fileName) => {
  6. blob.lastModifiedDate = new Date();
  7. blob.name = fileName;
  8. return blob;
  9. };

129.file转base64

  1. /**
  2. * @param { * } file 图片文件
  3. */
  4. export const fileToBase64 = file => {
  5. let reader = new FileReader();
  6. reader.readAsDataURL(file);
  7. reader.onload = function (e) {
  8. return e.target.result
  9. };
  10. };

130.递归生成树形结构

  1. export function getTreeData(data, pid, pidName = 'parentId', idName = 'id', childrenName = 'children', key) {
  2. let arr = [];
  3. for (let i = 0; i < data.length; i++) {
  4. if (data[i][pidName] == pid) {
  5. data[i].key = data[i][idName];
  6. data[i][childrenName] = getTreeData(data, data[i][idName], pidName, idName, childrenName);
  7. arr.push(data[i]);
  8. }
  9. }
  10. return arr;
  11. }

131.遍历树节点

  1. export function foreachTree(data, childrenName = 'children', callback) {
  2. for (let i = 0; i < data.length; i++) {
  3. callback(data[i]);
  4. if (data[i][childrenName] && data[i][childrenName].length > 0) {
  5. foreachTree(data[i][childrenName], childrenName, callback);
  6. }
  7. }
  8. }

132.追溯父节点

  1. export function traceParentNode(pid, data, rootPid, pidName = 'parentId', idName = 'id', childrenName = 'children') {
  2. let arr = [];
  3. foreachTree(data, childrenName, (node) => {
  4. if (node[idName] == pid) {
  5. arr.push(node);
  6. if (node[pidName] != rootPid) {
  7. arr = arr.concat(traceParentNode(node[pidName], data, rootPid, pidName, idName));
  8. }
  9. }
  10. });
  11. return arr;
  12. }

133.寻找所有子节点

  1. export function traceChildNode(id, data, pidName = 'parentId', idName = 'id', childrenName = 'children') {
  2. let arr = [];
  3. foreachTree(data, childrenName, (node) => {
  4. if (node[pidName] == id) {
  5. arr.push(node);
  6. arr = arr.concat(traceChildNode(node[idName], data, pidName, idName, childrenName));
  7. }
  8. });
  9. return arr;
  10. }

134.根据pid生成树形结构

  1. /**
  2. * @param { object } items 后台获取的数据
  3. * @param { * } id 数据中的id
  4. * @param { * } link 生成树形结构的依据
  5. */
  6. export const createTree = (items, id = null, link = 'pid') =>{
  7. items.filter(item => item[link] === id).map(item => ({ ...item, children: createTree(items, item.id) }));
  8. };

135.查询数组中是否存在某个元素并返回元素第一次出现的下标

  1. /**
  2. * @param {*} item
  3. * @param { array } data
  4. */
  5. export function inArray(item, data) {
  6. for (let i = 0; i < data.length; i++) {
  7. if (item === data[i]) {
  8. return i;
  9. }
  10. }
  11. return -1;
  12. }

136.Windows根据详细版本号判断当前系统名称

  1. /**
  2. * @param { string } osVersion
  3. */
  4. export function OutOsName(osVersion) {
  5. if(!osVersion){
  6. return
  7. }
  8. let str = osVersion.substr(0, 3);
  9. if (str === "5.0") {
  10. return "Win 2000"
  11. } else if (str === "5.1") {
  12. return "Win XP"
  13. } else if (str === "5.2") {
  14. return "Win XP64"
  15. } else if (str === "6.0") {
  16. return "Win Vista"
  17. } else if (str === "6.1") {
  18. return "Win 7"
  19. } else if (str === "6.2") {
  20. return "Win 8"
  21. } else if (str === "6.3") {
  22. return "Win 8.1"
  23. } else if (str === "10.") {
  24. return "Win 10"
  25. } else {
  26. return "Win"
  27. }
  28. }

137.判断手机是Andoird还是IOS

  1. /**
  2. * 0: ios
  3. * 1: android
  4. * 2: 其它
  5. */
  6. export function getOSType() {
  7. let u = navigator.userAgent, app = navigator.appVersion;
  8. let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
  9. let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  10. if (isIOS) {
  11. return 0;
  12. }
  13. if (isAndroid) {
  14. return 1;
  15. }
  16. return 2;
  17. }

138.函数防抖

  1. /**
  2. * @param { function } func
  3. * @param { number } wait 延迟执行毫秒数
  4. * @param { boolean } immediate true 表立即执行,false 表非立即执行
  5. */
  6. export function debounce(func,wait,immediate) {
  7. let timeout;
  8. return function () {
  9. let context = this;
  10. let args = arguments;
  11. if (timeout) clearTimeout(timeout);
  12. if (immediate) {
  13. let callNow = !timeout;
  14. timeout = setTimeout(() => {
  15. timeout = null;
  16. }, wait);
  17. if (callNow) func.apply(context, args)
  18. }
  19. else {
  20. timeout = setTimeout(() => {
  21. func.apply(context, args)
  22. }, wait);
  23. }
  24. }
  25. }

139.函数节流

  1. /**
  2. * @param { function } func 函数
  3. * @param { number } wait 延迟执行毫秒数
  4. * @param { number } type 1 表时间戳版,2 表定时器版
  5. */
  6. export function throttle(func, wait ,type) {
  7. let previous, timeout;
  8. if(type===1){
  9. previous = 0;
  10. }else if(type===2){
  11. timeout = null;
  12. }
  13. return function() {
  14. let context = this;
  15. let args = arguments;
  16. if(type===1){
  17. let now = Date.now();
  18. if (now - previous > wait) {
  19. func.apply(context, args);
  20. previous = now;
  21. }
  22. }else if(type===2){
  23. if (!timeout) {
  24. timeout = setTimeout(() => {
  25. timeout = null;
  26. func.apply(context, args)
  27. }, wait)
  28. }
  29. }
  30. }
  31. }

140.判断数据类型

  1. /**
  2. * @param {*} target
  3. */
  4. export function type(target) {
  5. let ret = typeof(target);
  6. let template = {
  7. "[object Array]": "array",
  8. "[object Object]":"object",
  9. "[object Number]":"number - object",
  10. "[object Boolean]":"boolean - object",
  11. "[object String]":'string-object'
  12. };
  13. if(target === null) {
  14. return 'null';
  15. }else if(ret == "object"){
  16. let str = Object.prototype.toString.call(target);
  17. return template[str];
  18. }else{
  19. return ret;
  20. }
  21. }

141.生成指定范围随机数

  1. /**
  2. * @param { number } min
  3. * @param { number } max
  4. */
  5. export const RandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

142.数组乱序

  1. /**
  2. * @param {array} arr
  3. */
  4. export function arrScrambling(arr) {
  5. let array = arr;
  6. let index = array.length;
  7. while (index) {
  8. index -= 1;
  9. let randomIndex = Math.floor(Math.random() * index);
  10. let middleware = array[index];
  11. array[index] = array[randomIndex];
  12. array[randomIndex] = middleware
  13. }
  14. return array
  15. }

143.数组交集

  1. /**
  2. * @param { array} arr1
  3. * @param { array } arr2
  4. */
  5. export const similarity = (arr1, arr2) => arr1.filter(v => arr2.includes(v));

144.数组中某元素出现的次数

  1. /**
  2. * @param { array } arr
  3. * @param {*} value
  4. */
  5. export function countOccurrences(arr, value) {
  6. return arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
  7. }

145.加法函数(精度丢失问题)

  1. /**
  2. * @param { number } arg1
  3. * @param { number } arg2
  4. */
  5. export function add(arg1, arg2) {
  6. let r1, r2, m;
  7. try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  8. try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  9. m = Math.pow(10, Math.max(r1, r2));
  10. return (arg1 * m + arg2 * m) / m
  11. }

146.减法函数(精度丢失问题)

  1. /**
  2. * @param { number } arg1
  3. * @param { number } arg2
  4. */
  5. export function sub(arg1, arg2) {
  6. let r1, r2, m, n;
  7. try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  8. try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  9. m = Math.pow(10, Math.max(r1, r2));
  10. n = (r1 >= r2) ? r1 : r2;
  11. return Number(((arg1 * m - arg2 * m) / m).toFixed(n));
  12. }

147.除法函数(精度丢失问题)

  1. /**
  2. * @param { number } num1
  3. * @param { number } num2
  4. */
  5. export function division(num1,num2){
  6. let t1,t2,r1,r2;
  7. try{
  8. t1 = num1.toString().split('.')[1].length;
  9. }catch(e){
  10. t1 = 0;
  11. }
  12. try{
  13. t2=num2.toString().split(".")[1].length;
  14. }catch(e){
  15. t2=0;
  16. }
  17. r1=Number(num1.toString().replace(".",""));
  18. r2=Number(num2.toString().replace(".",""));
  19. return (r1/r2)*Math.pow(10,t2-t1);
  20. }

148.乘法函数(精度丢失问题)

  1. /**
  2. * @param { number } num1
  3. * @param { number } num2
  4. */
  5. export function mcl(num1,num2){
  6. let m=0,s1=num1.toString(),s2=num2.toString();
  7. try{m+=s1.split(".")[1].length}catch(e){}
  8. try{m+=s2.split(".")[1].length}catch(e){}
  9. return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
  10. }

149.递归优化(尾递归)

  1. /**
  2. * @param { function } f
  3. */
  4. export function tco(f) {
  5. let value;
  6. let active = false;
  7. let accumulated = [];
  8. return function accumulator() {
  9. accumulated.push(arguments);
  10. if (!active) {
  11. active = true;
  12. while (accumulated.length) {
  13. value = f.apply(this, accumulated.shift());
  14. }
  15. active = false;
  16. return value;
  17. }
  18. };
  19. }

150.生成随机整数

  1. export function randomNumInteger(min, max) {
  2. switch (arguments.length) {
  3. case 1:
  4. return parseInt(Math.random() * min + 1, 10);
  5. case 2:
  6. return parseInt(Math.random() * (max - min + 1) + min, 10);
  7. default:
  8. return 0
  9. }
  10. }

151.去除空格

  1. /**
  2. * @param { string } str 待处理字符串
  3. * @param { number } type 去除空格类型 1-所有空格 2-前后空格 3-前空格 4-后空格 默认为1
  4. */
  5. export function trim(str, type = 1) {
  6. if (type && type !== 1 && type !== 2 && type !== 3 && type !== 4) return;
  7. switch (type) {
  8. case 1:
  9. return str.replace(/\s/g, "");
  10. case 2:
  11. return str.replace(/(^\s)|(\s*$)/g, "");
  12. case 3:
  13. return str.replace(/(^\s)/g, "");
  14. case 4:
  15. return str.replace(/(\s$)/g, "");
  16. default:
  17. return str;
  18. }
  19. }

152.大小写转换

  1. /**
  2. * @param { string } str 待转换的字符串
  3. * @param { number } type 1-全大写 2-全小写 3-首字母大写 其他-不转换
  4. */
  5. export function turnCase(str, type) {
  6. switch (type) {
  7. case 1:
  8. return str.toUpperCase();
  9. case 2:
  10. return str.toLowerCase();
  11. case 3:
  12. return str[0].toUpperCase() + str.substr(1).toLowerCase();
  13. default:
  14. return str;
  15. }
  16. }

153.随机16进制颜色 hexColor

  1. /**
  2. * 方法一
  3. */
  4. export function hexColor() {
  5. let str = '#';
  6. let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'];
  7. for (let i = 0; i < 6; i++) {
  8. let index = Number.parseInt((Math.random() * 16).toString());
  9. str += arr[index]
  10. }
  11. return str;
  12. }

154.随机16进制颜色 randomHexColorCode

  1. /**
  2. * 方法二
  3. */
  4. export const randomHexColorCode = () => {
  5. let n = (Math.random() * 0xfffff * 1000000).toString(16);
  6. return '#' + n.slice(0, 6);
  7. };

155.转义html(防XSS攻击)

  1. export const escapeHTML = str =>{
  2. str.replace(
  3. /[&<>'"]/g,
  4. tag =>
  5. ({
  6. '&': '&amp;',
  7. '<': '&lt;',
  8. '>': '&gt;',
  9. "'": '&#39;',
  10. '"': '&quot;'
  11. }[tag] || tag)
  12. );
  13. };

156.检测移动/PC设备

  1. export const detectDeviceType = () => { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop'; };

157.隐藏所有指定标签

  1. /**
  2. * 例: hide(document.querySelectorAll('img'))
  3. */
  4. export const hideTag = (...el) => [...el].forEach(e => (e.style.display = 'none'));

158.返回指定元素的生效样式

  1. /**
  2. * @param { element} el 元素节点
  3. * @param { string } ruleName 指定元素的名称
  4. */
  5. export const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];

159.检查是否包含子元素

  1. /**
  2. * @param { element } parent
  3. * @param { element } child
  4. * 例:elementContains(document.querySelector('head'), document.querySelector('title')); // true
  5. */
  6. export const elementContains = (parent, child) => parent !== child && parent.contains(child);

160.数字超过规定大小加上加号“+”,如数字超过99显示99+

  1. /**
  2. * @param { number } val 输入的数字
  3. * @param { number } maxNum 数字规定界限
  4. */
  5. export const outOfNum = (val, maxNum) =>{
  6. val = val ? val-0 :0;
  7. if (val > maxNum ) {
  8. return `${maxNum}+`
  9. }else{
  10. return val;
  11. }
  12. };

161.如何隐藏所有指定的元素

  1. const hide = (el) => Array.from(el).forEach(e => (e.style.display = 'none'));
  2. // 事例:隐藏页面上所有`<img>`元素?
  3. hide(document.querySelectorAll('img'))

162.如何检查元素是否具有指定的类?

页面DOM里的每个节点上都有一个classList对象,程序员可以使用里面的方法新增、删除、修改节点上的CSS类。使用classList,程序员还可以用它来判断某个节点是否被赋予了某个CSS类。

  1. const hasClass = (el, className) => el.classList.contains(className)
  2. // 事例
  3. hasClass(document.querySelector('p.special'), 'special') // true

163.如何切换一个元素的类?

  1. const toggleClass = (el, className) => el.classList.toggle(className)
  2. // 事例 移除 p 具有类`special`的 special 类
  3. toggleClass(document.querySelector('p.special'), 'special')

164.如何获取当前页面的滚动位置?

  1. const getScrollPosition = (el = window) => ({
  2. x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
  3. y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
  4. });
  5. // 事例
  6. getScrollPosition(); // {x: 0, y: 200}

165.如何平滑滚动到页面顶部

  1. const scrollToTop = () => {
  2. const c = document.documentElement.scrollTop || document.body.scrollTop;
  3. if (c > 0) {
  4. window.requestAnimationFrame(scrollToTop);
  5. window.scrollTo(0, c - c / 8);
  6. }
  7. }
  8. // 事例
  9. scrollToTop()
  10. window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
  11. requestAnimationFrame:优势:由系统决定回调函数的执行时机。60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。
  12. window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
  13. requestAnimationFrame:优势:由系统决定回调函数的执行时机。60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。

166.如何检查父元素是否包含子元素?

  1. const elementContains = (parent, child) => parent !== child && parent.contains(child);
  2. // 事例
  3. elementContains(document.querySelector('head'), document.querySelector('title'));
  4. // true
  5. elementContains(document.querySelector('body'), document.querySelector('body'));
  6. // false

167.如何检查指定的元素在视口中是否可见?

  1. const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
  2. const { top, left, bottom, right } = el.getBoundingClientRect();
  3. const { innerHeight, innerWidth } = window;
  4. return partiallyVisible
  5. ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
  6. ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
  7. : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
  8. };
  9. // 事例
  10. elementIsVisibleInViewport(el); // 需要左右可见
  11. elementIsVisibleInViewport(el, true); // 需要全屏(上下左右)可以见

168.如何获取元素中的所有图像?

  1. const getImages = (el, includeDuplicates = false) => {
  2. const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
  3. return includeDuplicates ? images : [...new Set(images)];
  4. };
  5. // 事例:includeDuplicates 为 true 表示需要排除重复元素
  6. getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...']
  7. getImages(document, false); // ['image1.jpg', 'image2.png', '...']

169.如何确定设备是移动设备还是台式机/笔记本电脑?

  1. const detectDeviceType = () =>
  2. /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
  3. ? 'Mobile'
  4. : 'Desktop';
  5. // 事例
  6. detectDeviceType(); // "Mobile" or "Desktop"

170.How to get the current URL?

  1. const currentURL = () => window.location.href
  2. // 事例
  3. currentURL() // 'https://google.com'

171.如何创建一个包含当前URL参数的对象?

  1. const getURLParameters = url =>
  2. (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
  3. (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
  4. {}
  5. );
  6. // 事例
  7. getURLParameters('http://url.com/page?n=Adam&s=Smith'); // {n: 'Adam', s: 'Smith'}
  8. getURLParameters('google.com'); // {}

172.如何将一组表单元素转化为对象?

  1. const formToObject = form =>
  2. Array.from(new FormData(form)).reduce(
  3. (acc, [key, value]) => ({
  4. ...acc,
  5. [key]: value
  6. }),
  7. {}
  8. );
  9. // 事例
  10. formToObject(document.querySelector('#form'));
  11. // { email: 'test@email.com', name: 'Test Name' }

173.如何从对象检索给定选择器指示的一组属性?

  1. const get = (from, ...selectors) =>
  2. [...selectors].map(s =>
  3. s
  4. .replace(/\[([^\[\]]*)\]/g, '.$1.')
  5. .split('.')
  6. .filter(t => t !== '')
  7. .reduce((prev, cur) => prev && prev[cur], from)
  8. );
  9. const obj = { selector: { to: { val: 'val to select' } }, target: [1, 2, { a: 'test' }] };
  10. // Example
  11. get(obj, 'selector.to.val', 'target[0]', 'target[2].a');
  12. // ['val to select', 1, 'test']

174.如何在等待指定时间后调用提供的函数?

  1. const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
  2. delay(
  3. function(text) {
  4. console.log(text);
  5. },
  6. 1000,
  7. 'later'
  8. );
  9. // 1秒后打印 'later'

175.如何在给定元素上触发特定事件且能选择地传递自定义数据?

  1. const triggerEvent = (el, eventType, detail) =>
  2. el.dispatchEvent(new CustomEvent(eventType, { detail }));
  3. // 事例
  4. triggerEvent(document.getElementById('myId'), 'click');
  5. triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' });
  6. 自定义事件的函数有 EventCustomEvent dispatchEvent
  7. // 向 window派发一个resize内置事件
  8. window.dispatchEvent(new Event('resize'))
  9. // 直接自定义事件,使用 Event 构造函数:
  10. var event = new Event('build');
  11. var elem = document.querySelector('#id')
  12. // 监听事件
  13. elem.addEventListener('build', function (e) { ... }, false);
  14. // 触发事件.
  15. elem.dispatchEvent(event);
  16. CustomEvent 可以创建一个更高度自定义事件,还可以附带一些数据,具体用法如下:
  17. var myEvent = new CustomEvent(eventname, options);
  18. 其中 options 可以是:
  19. {
  20. detail: {
  21. ...
  22. },
  23. bubbles: true, //是否冒泡
  24. cancelable: false //是否取消默认事件
  25. }
  26. 其中 detail 可以存放一些初始化的信息,可以在触发的时候调用。其他属性就是定义该事件是否具有冒泡等等功能。
  27. 内置的事件会由浏览器根据某些操作进行触发,自定义的事件就需要人工触发。
  28. dispatchEvent 函数就是用来触发某个事件:
  29. element.dispatchEvent(customEvent);
  30. 上面代码表示,在 element 上面触发 customEvent 这个事件。
  31. // add an appropriate event listener
  32. obj.addEventListener("cat", function(e) { process(e.detail) });
  33. // create and dispatch the event
  34. var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}});
  35. obj.dispatchEvent(event);
  36. 使用自定义事件需要注意兼容性问题,而使用 jQuery 就简单多了:
  37. // 绑定自定义事件
  38. $(element).on('myCustomEvent', function(){});
  39. // 触发事件
  40. $(element).trigger('myCustomEvent');
  41. // 此外,你还可以在触发自定义事件时传递更多参数信息:
  42. $( "p" ).on( "myCustomEvent", function( event, myName ) {
  43. $( this ).text( myName + ", hi there!" );
  44. });
  45. $( "button" ).click(function () {
  46. $( "p" ).trigger( "myCustomEvent", [ "John" ] );
  47. });

176.如何从元素中移除事件监听器?

  1. const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);
  2. const fn = () => console.log('!');
  3. document.body.addEventListener('click', fn);
  4. off(document.body, 'click', fn);

177.如何获得给定毫秒数的可读格式?

  1. const formatDuration = ms => {
  2. if (ms < 0) ms = -ms;
  3. const time = {
  4. day: Math.floor(ms / 86400000),
  5. hour: Math.floor(ms / 3600000) % 24,
  6. minute: Math.floor(ms / 60000) % 60,
  7. second: Math.floor(ms / 1000) % 60,
  8. millisecond: Math.floor(ms) % 1000
  9. };
  10. return Object.entries(time)
  11. .filter(val => val[1] !== 0)
  12. .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
  13. .join(', ');
  14. };
  15. // 事例
  16. formatDuration(1001); // '1 second, 1 millisecond'
  17. formatDuration(34325055574);
  18. // '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds'