- 128.blob转file
- 129.file转base64
- 130.递归生成树形结构
- 131.遍历树节点
- 132.追溯父节点
- 133.寻找所有子节点
- 134.根据pid生成树形结构
- 135.查询数组中是否存在某个元素并返回元素第一次出现的下标
- 136.Windows根据详细版本号判断当前系统名称
- 137.判断手机是Andoird还是IOS
- 138.函数防抖
- 139.函数节流
- 140.判断数据类型
- 141.生成指定范围随机数
- 142.数组乱序
- 143.数组交集
- 144.数组中某元素出现的次数
- 145.加法函数(精度丢失问题)
- 146.减法函数(精度丢失问题)
- 147.除法函数(精度丢失问题)
- 148.乘法函数(精度丢失问题)
- 149.递归优化(尾递归)
- 150.生成随机整数
- 151.去除空格
- 152.大小写转换
- 153.随机16进制颜色 hexColor
- 154.随机16进制颜色 randomHexColorCode
- 155.转义html(防XSS攻击)
- 156.检测移动/PC设备
- 157.隐藏所有指定标签
- 158.返回指定元素的生效样式
- 159.检查是否包含子元素
- 160.数字超过规定大小加上加号“+”,如数字超过99显示99+
- 161.如何隐藏所有指定的元素
- 162.如何检查元素是否具有指定的类?
- 163.如何切换一个元素的类?
- 164.如何获取当前页面的滚动位置?
- 165.如何平滑滚动到页面顶部
- 166.如何检查父元素是否包含子元素?
- 167.如何检查指定的元素在视口中是否可见?
- 168.如何获取元素中的所有图像?
- 169.如何确定设备是移动设备还是台式机/笔记本电脑?
- 170.How to get the current URL?
- 171.如何创建一个包含当前URL参数的对象?
- 172.如何将一组表单元素转化为对象?
- 173.如何从对象检索给定选择器指示的一组属性?
- 174.如何在等待指定时间后调用提供的函数?
- 175.如何在给定元素上触发特定事件且能选择地传递自定义数据?
- 176.如何从元素中移除事件监听器?
- 177.如何获得给定毫秒数的可读格式?
文章摘自269个工具函数库:269个工具函数库下
128.blob转file
/*** @param { blob } blob* @param { string } fileName*/export const blobToFile = (blob, fileName) => {blob.lastModifiedDate = new Date();blob.name = fileName;return blob;};
129.file转base64
/*** @param { * } file 图片文件*/export const fileToBase64 = file => {let reader = new FileReader();reader.readAsDataURL(file);reader.onload = function (e) {return e.target.result};};
130.递归生成树形结构
export function getTreeData(data, pid, pidName = 'parentId', idName = 'id', childrenName = 'children', key) {let arr = [];for (let i = 0; i < data.length; i++) {if (data[i][pidName] == pid) {data[i].key = data[i][idName];data[i][childrenName] = getTreeData(data, data[i][idName], pidName, idName, childrenName);arr.push(data[i]);}}return arr;}
131.遍历树节点
export function foreachTree(data, childrenName = 'children', callback) {for (let i = 0; i < data.length; i++) {callback(data[i]);if (data[i][childrenName] && data[i][childrenName].length > 0) {foreachTree(data[i][childrenName], childrenName, callback);}}}
132.追溯父节点
export function traceParentNode(pid, data, rootPid, pidName = 'parentId', idName = 'id', childrenName = 'children') {let arr = [];foreachTree(data, childrenName, (node) => {if (node[idName] == pid) {arr.push(node);if (node[pidName] != rootPid) {arr = arr.concat(traceParentNode(node[pidName], data, rootPid, pidName, idName));}}});return arr;}
133.寻找所有子节点
export function traceChildNode(id, data, pidName = 'parentId', idName = 'id', childrenName = 'children') {let arr = [];foreachTree(data, childrenName, (node) => {if (node[pidName] == id) {arr.push(node);arr = arr.concat(traceChildNode(node[idName], data, pidName, idName, childrenName));}});return arr;}
134.根据pid生成树形结构
/*** @param { object } items 后台获取的数据* @param { * } id 数据中的id* @param { * } link 生成树形结构的依据*/export const createTree = (items, id = null, link = 'pid') =>{items.filter(item => item[link] === id).map(item => ({ ...item, children: createTree(items, item.id) }));};
135.查询数组中是否存在某个元素并返回元素第一次出现的下标
/*** @param {*} item* @param { array } data*/export function inArray(item, data) {for (let i = 0; i < data.length; i++) {if (item === data[i]) {return i;}}return -1;}
136.Windows根据详细版本号判断当前系统名称
/*** @param { string } osVersion*/export function OutOsName(osVersion) {if(!osVersion){return}let str = osVersion.substr(0, 3);if (str === "5.0") {return "Win 2000"} else if (str === "5.1") {return "Win XP"} else if (str === "5.2") {return "Win XP64"} else if (str === "6.0") {return "Win Vista"} else if (str === "6.1") {return "Win 7"} else if (str === "6.2") {return "Win 8"} else if (str === "6.3") {return "Win 8.1"} else if (str === "10.") {return "Win 10"} else {return "Win"}}
137.判断手机是Andoird还是IOS
/*** 0: ios* 1: android* 2: 其它*/export function getOSType() {let u = navigator.userAgent, app = navigator.appVersion;let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);if (isIOS) {return 0;}if (isAndroid) {return 1;}return 2;}
138.函数防抖
/*** @param { function } func* @param { number } wait 延迟执行毫秒数* @param { boolean } immediate true 表立即执行,false 表非立即执行*/export function debounce(func,wait,immediate) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);if (immediate) {let callNow = !timeout;timeout = setTimeout(() => {timeout = null;}, wait);if (callNow) func.apply(context, args)}else {timeout = setTimeout(() => {func.apply(context, args)}, wait);}}}
139.函数节流
/*** @param { function } func 函数* @param { number } wait 延迟执行毫秒数* @param { number } type 1 表时间戳版,2 表定时器版*/export function throttle(func, wait ,type) {let previous, timeout;if(type===1){previous = 0;}else if(type===2){timeout = null;}return function() {let context = this;let args = arguments;if(type===1){let now = Date.now();if (now - previous > wait) {func.apply(context, args);previous = now;}}else if(type===2){if (!timeout) {timeout = setTimeout(() => {timeout = null;func.apply(context, args)}, wait)}}}}
140.判断数据类型
/*** @param {*} target*/export function type(target) {let ret = typeof(target);let template = {"[object Array]": "array","[object Object]":"object","[object Number]":"number - object","[object Boolean]":"boolean - object","[object String]":'string-object'};if(target === null) {return 'null';}else if(ret == "object"){let str = Object.prototype.toString.call(target);return template[str];}else{return ret;}}
141.生成指定范围随机数
/*** @param { number } min* @param { number } max*/export const RandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
142.数组乱序
/*** @param {array} arr*/export function arrScrambling(arr) {let array = arr;let index = array.length;while (index) {index -= 1;let randomIndex = Math.floor(Math.random() * index);let middleware = array[index];array[index] = array[randomIndex];array[randomIndex] = middleware}return array}
143.数组交集
/*** @param { array} arr1* @param { array } arr2*/export const similarity = (arr1, arr2) => arr1.filter(v => arr2.includes(v));
144.数组中某元素出现的次数
/*** @param { array } arr* @param {*} value*/export function countOccurrences(arr, value) {return arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);}
145.加法函数(精度丢失问题)
/*** @param { number } arg1* @param { number } arg2*/export function add(arg1, arg2) {let r1, r2, m;try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }m = Math.pow(10, Math.max(r1, r2));return (arg1 * m + arg2 * m) / m}
146.减法函数(精度丢失问题)
/*** @param { number } arg1* @param { number } arg2*/export function sub(arg1, arg2) {let r1, r2, m, n;try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }m = Math.pow(10, Math.max(r1, r2));n = (r1 >= r2) ? r1 : r2;return Number(((arg1 * m - arg2 * m) / m).toFixed(n));}
147.除法函数(精度丢失问题)
/*** @param { number } num1* @param { number } num2*/export function division(num1,num2){let t1,t2,r1,r2;try{t1 = num1.toString().split('.')[1].length;}catch(e){t1 = 0;}try{t2=num2.toString().split(".")[1].length;}catch(e){t2=0;}r1=Number(num1.toString().replace(".",""));r2=Number(num2.toString().replace(".",""));return (r1/r2)*Math.pow(10,t2-t1);}
148.乘法函数(精度丢失问题)
/*** @param { number } num1* @param { number } num2*/export function mcl(num1,num2){let m=0,s1=num1.toString(),s2=num2.toString();try{m+=s1.split(".")[1].length}catch(e){}try{m+=s2.split(".")[1].length}catch(e){}return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);}
149.递归优化(尾递归)
/*** @param { function } f*/export function tco(f) {let value;let active = false;let accumulated = [];return function accumulator() {accumulated.push(arguments);if (!active) {active = true;while (accumulated.length) {value = f.apply(this, accumulated.shift());}active = false;return value;}};}
150.生成随机整数
export function randomNumInteger(min, max) {switch (arguments.length) {case 1:return parseInt(Math.random() * min + 1, 10);case 2:return parseInt(Math.random() * (max - min + 1) + min, 10);default:return 0}}
151.去除空格
/*** @param { string } str 待处理字符串* @param { number } type 去除空格类型 1-所有空格 2-前后空格 3-前空格 4-后空格 默认为1*/export function trim(str, type = 1) {if (type && type !== 1 && type !== 2 && type !== 3 && type !== 4) return;switch (type) {case 1:return str.replace(/\s/g, "");case 2:return str.replace(/(^\s)|(\s*$)/g, "");case 3:return str.replace(/(^\s)/g, "");case 4:return str.replace(/(\s$)/g, "");default:return str;}}
152.大小写转换
/*** @param { string } str 待转换的字符串* @param { number } type 1-全大写 2-全小写 3-首字母大写 其他-不转换*/export function turnCase(str, type) {switch (type) {case 1:return str.toUpperCase();case 2:return str.toLowerCase();case 3:return str[0].toUpperCase() + str.substr(1).toLowerCase();default:return str;}}
153.随机16进制颜色 hexColor
/*** 方法一*/export function hexColor() {let str = '#';let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'];for (let i = 0; i < 6; i++) {let index = Number.parseInt((Math.random() * 16).toString());str += arr[index]}return str;}
154.随机16进制颜色 randomHexColorCode
/*** 方法二*/export const randomHexColorCode = () => {let n = (Math.random() * 0xfffff * 1000000).toString(16);return '#' + n.slice(0, 6);};
155.转义html(防XSS攻击)
export const escapeHTML = str =>{str.replace(/[&<>'"]/g,tag =>({'&': '&','<': '<','>': '>',"'": ''','"': '"'}[tag] || tag));};
156.检测移动/PC设备
export const detectDeviceType = () => { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop'; };
157.隐藏所有指定标签
/*** 例: hide(document.querySelectorAll('img'))*/export const hideTag = (...el) => [...el].forEach(e => (e.style.display = 'none'));
158.返回指定元素的生效样式
/*** @param { element} el 元素节点* @param { string } ruleName 指定元素的名称*/export const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
159.检查是否包含子元素
/*** @param { element } parent* @param { element } child* 例:elementContains(document.querySelector('head'), document.querySelector('title')); // true*/export const elementContains = (parent, child) => parent !== child && parent.contains(child);
160.数字超过规定大小加上加号“+”,如数字超过99显示99+
/*** @param { number } val 输入的数字* @param { number } maxNum 数字规定界限*/export const outOfNum = (val, maxNum) =>{val = val ? val-0 :0;if (val > maxNum ) {return `${maxNum}+`}else{return val;}};
161.如何隐藏所有指定的元素
const hide = (el) => Array.from(el).forEach(e => (e.style.display = 'none'));// 事例:隐藏页面上所有`<img>`元素?hide(document.querySelectorAll('img'))
162.如何检查元素是否具有指定的类?
页面DOM里的每个节点上都有一个classList对象,程序员可以使用里面的方法新增、删除、修改节点上的CSS类。使用classList,程序员还可以用它来判断某个节点是否被赋予了某个CSS类。
const hasClass = (el, className) => el.classList.contains(className)// 事例hasClass(document.querySelector('p.special'), 'special') // true
163.如何切换一个元素的类?
const toggleClass = (el, className) => el.classList.toggle(className)// 事例 移除 p 具有类`special`的 special 类toggleClass(document.querySelector('p.special'), 'special')
164.如何获取当前页面的滚动位置?
const getScrollPosition = (el = window) => ({x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop});// 事例getScrollPosition(); // {x: 0, y: 200}
165.如何平滑滚动到页面顶部
const scrollToTop = () => {const c = document.documentElement.scrollTop || document.body.scrollTop;if (c > 0) {window.requestAnimationFrame(scrollToTop);window.scrollTo(0, c - c / 8);}}// 事例scrollToTop()window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。requestAnimationFrame:优势:由系统决定回调函数的执行时机。60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。requestAnimationFrame:优势:由系统决定回调函数的执行时机。60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。
166.如何检查父元素是否包含子元素?
const elementContains = (parent, child) => parent !== child && parent.contains(child);// 事例elementContains(document.querySelector('head'), document.querySelector('title'));// trueelementContains(document.querySelector('body'), document.querySelector('body'));// false
167.如何检查指定的元素在视口中是否可见?
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {const { top, left, bottom, right } = el.getBoundingClientRect();const { innerHeight, innerWidth } = window;return partiallyVisible? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)): top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;};// 事例elementIsVisibleInViewport(el); // 需要左右可见elementIsVisibleInViewport(el, true); // 需要全屏(上下左右)可以见
168.如何获取元素中的所有图像?
const getImages = (el, includeDuplicates = false) => {const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));return includeDuplicates ? images : [...new Set(images)];};// 事例:includeDuplicates 为 true 表示需要排除重复元素getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...']getImages(document, false); // ['image1.jpg', 'image2.png', '...']
169.如何确定设备是移动设备还是台式机/笔记本电脑?
const detectDeviceType = () =>/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)? 'Mobile': 'Desktop';// 事例detectDeviceType(); // "Mobile" or "Desktop"
170.How to get the current URL?
const currentURL = () => window.location.href// 事例currentURL() // 'https://google.com'
171.如何创建一个包含当前URL参数的对象?
const getURLParameters = url =>(url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce((a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),{});// 事例getURLParameters('http://url.com/page?n=Adam&s=Smith'); // {n: 'Adam', s: 'Smith'}getURLParameters('google.com'); // {}
172.如何将一组表单元素转化为对象?
const formToObject = form =>Array.from(new FormData(form)).reduce((acc, [key, value]) => ({...acc,[key]: value}),{});// 事例formToObject(document.querySelector('#form'));// { email: 'test@email.com', name: 'Test Name' }
173.如何从对象检索给定选择器指示的一组属性?
const get = (from, ...selectors) =>[...selectors].map(s =>s.replace(/\[([^\[\]]*)\]/g, '.$1.').split('.').filter(t => t !== '').reduce((prev, cur) => prev && prev[cur], from));const obj = { selector: { to: { val: 'val to select' } }, target: [1, 2, { a: 'test' }] };// Exampleget(obj, 'selector.to.val', 'target[0]', 'target[2].a');// ['val to select', 1, 'test']
174.如何在等待指定时间后调用提供的函数?
const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);delay(function(text) {console.log(text);},1000,'later');// 1秒后打印 'later'
175.如何在给定元素上触发特定事件且能选择地传递自定义数据?
const triggerEvent = (el, eventType, detail) =>el.dispatchEvent(new CustomEvent(eventType, { detail }));// 事例triggerEvent(document.getElementById('myId'), 'click');triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' });自定义事件的函数有 Event、CustomEvent 和 dispatchEvent// 向 window派发一个resize内置事件window.dispatchEvent(new Event('resize'))// 直接自定义事件,使用 Event 构造函数:var event = new Event('build');var elem = document.querySelector('#id')// 监听事件elem.addEventListener('build', function (e) { ... }, false);// 触发事件.elem.dispatchEvent(event);CustomEvent 可以创建一个更高度自定义事件,还可以附带一些数据,具体用法如下:var myEvent = new CustomEvent(eventname, options);其中 options 可以是:{detail: {...},bubbles: true, //是否冒泡cancelable: false //是否取消默认事件}其中 detail 可以存放一些初始化的信息,可以在触发的时候调用。其他属性就是定义该事件是否具有冒泡等等功能。内置的事件会由浏览器根据某些操作进行触发,自定义的事件就需要人工触发。dispatchEvent 函数就是用来触发某个事件:element.dispatchEvent(customEvent);上面代码表示,在 element 上面触发 customEvent 这个事件。// add an appropriate event listenerobj.addEventListener("cat", function(e) { process(e.detail) });// create and dispatch the eventvar event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}});obj.dispatchEvent(event);使用自定义事件需要注意兼容性问题,而使用 jQuery 就简单多了:// 绑定自定义事件$(element).on('myCustomEvent', function(){});// 触发事件$(element).trigger('myCustomEvent');// 此外,你还可以在触发自定义事件时传递更多参数信息:$( "p" ).on( "myCustomEvent", function( event, myName ) {$( this ).text( myName + ", hi there!" );});$( "button" ).click(function () {$( "p" ).trigger( "myCustomEvent", [ "John" ] );});
176.如何从元素中移除事件监听器?
const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);const fn = () => console.log('!');document.body.addEventListener('click', fn);off(document.body, 'click', fn);
177.如何获得给定毫秒数的可读格式?
const formatDuration = ms => {if (ms < 0) ms = -ms;const time = {day: Math.floor(ms / 86400000),hour: Math.floor(ms / 3600000) % 24,minute: Math.floor(ms / 60000) % 60,second: Math.floor(ms / 1000) % 60,millisecond: Math.floor(ms) % 1000};return Object.entries(time).filter(val => val[1] !== 0).map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`).join(', ');};// 事例formatDuration(1001); // '1 second, 1 millisecond'formatDuration(34325055574);// '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds'
