https://www.imqianduan.com/javascript/236.html
https://juejin.cn/post/6898962197335490573
策略模式 https://www.cnblogs.com/hollischuang/p/13186766.html
https://blog.csdn.net/qq_34703156/article/details/122863975
https://blog.csdn.net/java_atguigu/article/details/123919921
https://baijiahao.baidu.com/s?id=1713405091858312136&wfr=spider&for=pc
https://www.cnblogs.com/shine-lovely/p/12836773.html
https://www.cnblogs.com/fundebug/p/13_js_utilities_you_need.html
https://gitee.com/zhangyangbin/js-utils
https://github.com/proYang/outils
https://juejin.cn/post/7048963605462515743
异步并发限制 https://zhuanlan.zhihu.com/p/123968952
utils
number
string
date
cache
is判断类型,设备类型
语雀空间
https://xk70b1.yuque.com/dashboard
https://www.yuque.com/yuque/blog/hrwynrqgoexdynw4
collect
https://github.com/ecrmnn/collect.js
https://collect.js.org/installation.html
yarn add collect.js
mathjs
https://github.com/josdejong/mathjs
https://mathjs.org/
sugarjs
sugarjs https://sugarjs.com/
lazy.js
https://github.com/dtao/lazy.js
http://danieltao.com/lazy.js/
函数调用// 冗余function test1() { console.log('test1'); };function test2() { console.log('test2'); };var test3 = 1;if (test3 == 1) { test1(); }else { test2(); }// 简单(test3 === 1? test1:test2)();多行字符串// 冗余const data = 'abc abc abc abc abc abc\n\t'+ 'test test,test test test test\n\t'// 简洁const data = `abc abc abc abc abc abctest test,test test test test`隐式返回// 冗余function getArea(diameter) {return Math.PI * diameter}// 简洁getArea = diameter => (Math.PI * diameter;)字符串重复多次// 冗余let test = '';for(let i = 0; i < 5; i ++) {test += 'test ';}// 简洁'test '.repeat(5);幂乘// 冗余Math.pow(2,3);// 简洁而2**3 // 8获取对象的key, value值Object.keys()、Object.values()、Object.entries()的用法图片懒加载可以通过为图片文件添加loading="lazy"的属性来实现:数组去重1.借助Setconst arr = [12,34,565,12,34,1,3,1]const newArr = Array.from(new Set(arr))console.log('newArr',newArr);const numbers = [1,2,3,4,1,2,3,4];const result = [... new Set(numbers)];?.链式合并运算// 错误写法,当某一层级值为null或undefined时,会报错const userName = list.info.base.userName;// 正确写法(我们常用的方式)const userName = (list && list.info && list.info.base &&list.info.base.userName) || 'userName'// 错误写法,当某一层级值为null或undefined时,会报错const userName = list.info.base.userName;// 正确写法(我们常用的方式)const userName = (list && list.info && list.info.base &&list.info.base.userName) || 'userName'es2020引入链合并运算符,简化上面的写法const userName = list?.info?.base?.userName || 'userName';?.运算符这在有时候处理对象时非常有用,看下面案例,person.name返回undefined然后在调用toString这时肯定会报错,这时使用?.运算符就不会产生错误,?.运算符是只有在当值不是undefined时才会调用toString方法。双位运算符双位运算符比Math.floor(),Math.ceil()速度快`~~7.5 // 7Math.ceil(7.5) // 8Math.floor(7.5) // 7~~-7.5 // -7Math.floor(-7.5) // -8Math.ceil(-7.5) // -7~~双非运算符~~双非运算符可以用于向下取整console.log(~~4.3) // 4??运算符只有前面的值是undefined or null才会执行,工作中有的情况下使用,我们来看一下。let status = undefined;let text = status ?? "暂无"console.log(text) // 暂无??的意思是 如果?? 左边的值是null 或者是undefined,那么就返回右边的const height = 0console.log(height||100)//100cosole.log(height ?? 100)//0检查数值是不是NANNumber.isNaN(1+NaN); // true; NaN 数值与非数值运算的结果NaN深度 cloneconst objectA = {a: 1, b: 2};const clonedA = JSON.parse(JSON.stringify(objectA));字符串转数字let numberStr = "123";+numberStr; // 123numberStr = '123.12';+numberStr; // 123.12数字转字符串直接在需要转换的数字后加上空字符串,最快捷的转换,比调用toString快很多判断正负值// Math.sign()// 判断正负, 还是0; 对非数值,能转化的转化; 不能转的就是NaN// 返回值: 正 +1; 负 -1; 0; 0; 其他值 NaNArray.of(传一组数值); 用于将一组值,转换为数组Array.from(param1, param2)方法用于将两类对象转为真正的数组参数1: 一个对象 ==> 伪数组对象和可遍历(iterable)的对象参数2: 回调函数 ==> 类似于数组的map方法,对每个元素进行处理,将处理后的值放入返回的数组。return值: 一个数组;示例:let arrayLike = {'0': 'a','1': 'b','2': 'c',length: 3// 0: 'a',// 1: 'b',// 2: 'c',// length: 3};let real_arr = Array.from(arrayLike);在两个数组匹配取值的情况,如果嵌套循环,效率低,并且代码看着不美观。利用对象的特性,可以简化复杂度。例如根据id匹配员工工资双数组匹配const employees = [{id: 1, name: 'Tom'},{id: 2, name: 'Jerry'},{id: 3, name: 'Jim'},{id: 4, name: 'Kate'}];const salary = [{id: 1, salary: 10000},{id: 2, salary: 20000},{id: 3, salary: 30000},{id: 4, salary: 40000}];const salaryObj = {};salary.map(({id, salary}) => salaryObj[id] = salary);employees.map(e => e.salary = salaryObj[e.id]);JavaScript 中只有六个虚值undefinednullNaN0"" (空字符串)falsemyArray.filter(Boolean);去除当前数组里的false值# !!!!0; // false!!undefined; // false!!null; // false!!(()=>{}); // true原始的 myArray 会保持不变myArray.map(item => {// Do your changes and return the new item}).filter(Boolean);合并多个对象const user = {name: 'John Ludwig',gender: 'Male'};const college = {primary: 'Mani Primary School',secondary: 'Lass Secondary School'};const skills = {programming: 'Extreme',swimming: 'Average',sleeping: 'Pro'};const summary = {...user, ...college, ...skills};数组排序默认情况下 sort 方法把数组元素转换为字符串,并对其进行字典排序。在对数字数组进行排序时,这有可能会导致一些问题[0,10,4,9,123,54,1].sort((a,b) => a-b);[0, 1, 4, 9, 10, 54, 123]阻止用户在你的网页上单击鼠标右键<body oncontextmenu="return false"><div></div></body>获取数组中的最后一项过对 splice 方法的参数传入负整数,来数获取组末尾的元素let array = [0, 1, 2, 3, 4, 5, 6, 7]console.log(array.slice(-1));[7]console.log(array.slice(-2));[6, 7]console.log(array.slice(-3));[5, 6, 7]Promise.all 的主要注意事项是,当一个 Promise 拒绝时,该方法将引发错误。这意味着你的代码不会等到你所有的 promise 都完成等到所有 promise 都完成后,无论它们被拒绝还是被解决,都可以使用 Promise.allSettled。此方法在 ES2020 的最终版本得到支持即使某些 promise 被拒绝,Promise.allSettled 也会从你所有的 promise 中返回结果const PromiseArray = [Promise.resolve(100),Promise.reject(null),Promise.resolve("Data release"),Promise.reject(new Error('Something went wrong'))];Promise.allSettled(PromiseArray).then(res =>{console.log(res);}).catch(err => console.log(err));//[//{status: "fulfilled", value: 100},//{status: "rejected", reason: null},//{status: "fulfilled", value: "Data release"},//{status: "rejected", reason: Error: Something went wrong ...}//]try..catch..finallyconst getData = async () => {try {setLoading(true);const response = await fetch("https://jsonplaceholder.typicode.com/posts");const data = await response.json();setData(data);} catch (error) {console.log(error);setToastMessage(error);} finally {setLoading(false); // 不管是否报错,最后都会执行}};getData();别名结构赋值const object = { number: 10 };// Grabbing numberconst { number } = object;// Grabbing number and renaming it as otherNumberconst { number: otherNumber } = object;console.log(otherNumber); //10eval 生成正则表达式,动态正则匹配let str = 'hello world ';let reg1 = `/hello/g`;let reg2 = `/world/g`;eval(reg1).test(str); // trueeval(reg2).test(str); // true
Form表单
String字符串
https://github.com/jprichardson/string.js
文本选中
https://github.com/EvandroLG/selecting
npm install selecting

音频&视频
图片相关
轮播图
https://github.com/sachinchoolur/lightgallery.js
https://github.com/fengyuanchen/cropperjs
https://fengyuanchen.github.io/viewerjs/
图片懒加载
https://github.com/dinbror/blazy/
https://dinbror.dk/blazy/?ref=github
JS数据可视化
- d3.js
- three.js
- echarts.js
BOM操作
domurl
https://github.com/Mikhus/domurl
npm install domurl
urijs
import URI from 'urijs'
禁止页面另存为:标签加入以下代码
<noscript><iframe src=”*.htm”></iframe></noscript>
禁止复制页面内容
<bodyοncοntextmenu=”return false” 禁止鼠标右键菜单onselectstart=”return false” 禁止鼠标选取οndragstart=”return false” 禁止鼠标拖拽></body>
html encode & decode
https://github.com/mathiasbynens/he
原生JS的重要性
你不需要 lodash
- You may not need Lodash / Underscore
- https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore
你不需要 Jquery
function loop(array, fn){for ( var i = 0; i < array.length; i++ )fn.call( array, array[i], i );}// 最小值function smallest(array){return Math.min.apply( Math, array );}// 最大值function largest(array){return Math.max.apply( Math, array );}// sleepconst sleep = ms => new Promise(resolve => setTimeout(() => resolve(), ms))/*** 函数防抖* @params callback 回调函数* @param wait 延迟执行毫秒数* @param immediate true 表立即执行,false 表非立即执行*/function debounce(callback, wait, immediate) {let timeoutreturn function() {let _this = thislet args = arguments // arguments 必须在函数内部是用if(timeout) clearTimeout(timeout)if(immediate) {const callNow = !timeouttimeout = setTimeout(() => {timeout = null}, wait)if(callNow) func.apply(_this, args)}else {timeout = setTimeout(() => {callback.apply(_this, args)}, wait)}}}// 函数节流// Returns a function, that, when invoked, will only be triggered at most once// during a given window of time. Normally, the throttled function will run// as much as it can, without ever going more than once per `wait` duration;// but if you'd like to disable the execution on the leading edge, pass// `{leading: false}`. To disable execution on the trailing edge, ditto.function throttle(func, wait, options) {var context, args, result;var timeout = null;var previous = 0;if (!options) options = {};var later = function() {previous = options.leading === false ? 0 : Date.now();timeout = null;result = func.apply(context, args);if (!timeout) context = args = null;};return function() {var now = Date.now();if (!previous && options.leading === false) previous = now;var remaining = wait - (now - previous);context = this;args = arguments;if (remaining <= 0 || remaining > wait) {if (timeout) {clearTimeout(timeout);timeout = null;}previous = now;result = func.apply(context, args);if (!timeout) context = args = null;} else if (!timeout && options.trailing !== false) {timeout = setTimeout(later, remaining);}return result;};};// 数组去重的20中思路// setTimeout实现 setIntervalfunction _setInterval(){let timer = setTimeout(() =>{_setInterval()clearTimeout(timer)}, 1000)}function myInterval(callback, time){function inner() {callback()setTimeout(inner, time)}inner()}// 闭包(function(){const utils = window._utils_ = function() {}})();const utils = (function(){function utils() {}})()Object.prototype.keys = function(){var keys = [];for ( var i in this )keys.push( i );return keys;}Function.prototype.bind = function(object){var fn = this;return function(){return fn.apply(object, arguments);};};// 生成26个字母Array.from({length: 26}, (_, i) => String.fromCharCode(65+i))
本地字典
dict.js
// Badge 状态export const STATUS = {0: { label: '在线', value: 'green' }, // 绿1: { label: '故障', value: 'orange'}, // 橙2: { label: '预警', value: 'yellow' }, // 黄3: { label: '离线', value: 'default' }, // 灰}export const TIMESTAMP = {'h1': () => datenow() - oneHour,'h6': () => datenow() - oneHour * 6,'h12':() => datenow() - oneHour * 12,'day1':() => datenow() - oneDay,'day3':() => datenow() - oneDay * 3,'day7':() => datenow() - oneDay * 7,}
// JSON转字符串export function JsonEncode(obj) {return JSON.stringify(obj);}// 字符串转JSONexport function JsonDecode(str) {let value = '';try {value = JSON.parse(str);}catch(e) {// unquote 转义字符也会导致解析失败const newString = str.replace(/"/g, '\"');value = JSON.parse(newString);}return value;}// 转义 urlexport function DecodeUri(string) {const { decodeURIComponent, escape } = window;return decodeURIComponent(escape(string));}// 字符串转JSONexport function EncodeUri(string) {const { encodeURIComponent, unescape } = window;return unescape(encodeURIComponent(string));}// 获取 URL参数export function getParams() {const query = window.location.search.substr(1);const queryArray = query.split('&');return queryArray.reduce((prev, next) => {const [key, value] = next.split('=');prev[key] = value;return prev;}, {});}// 获取 URL参数,正则export function getParams() {const REG = /(([\w\-]+){1}(\=([^\&\n\r\t]*){1})?)/g;const query = REG.exec(window.location.search.substr(1));}export function getUrl() {return window.location.href;}export function isFile(url) {return url.includes('file://')}export function isHttp() {return url.includes('http://')}export function isHttps() {return url.includes('https://')}export function isLocalhost(url) {const reg = /^(https?\:\/\/)(localhost|127\.0\.0\.1)(\:[\d]+)?(\/(.)*)?$/;return reg.test(url);}// Numberexport function isFloat(value) {return value % 1 !== 0;}// type类型export function isDate(value) {return Object.prototype.toString.call(value) === '[object Date]';}export function isFunction(value) {return typeof (value) === 'function';}export function isArray(value) {if (Array.isArray) {return Array.isArray(value);}return (Object.prototype.toString.call(value) === '[object Array]');}export function isObject(value) {return Object.prototype.toString.call(value) === '[object Object]';}export function isBoolean() {return typeof (val) === 'boolean'}export function isError(value) {return value instanceof Error;}export function isNumber(value) {return typeof (value) === 'number' && !isNaN(value) && isFinite(value)}export function isNull() {// undefined, nullreturn value == null;}export function isRegExp(value) {return value instanceof RegExp;}export function isString(value) {return typeof (value) === 'string';}export function isJSON(value) {if (!isString(value)) return false;try {const values = JSON.parse(value);return values !== null && typeof (values) === 'object';} catch (e) {return false;}}export function isBase64() {if (!isString(value) || value.trim() === '') return false;try {return btoa(atob(value)) == value;} catch (e) {return false;}}export function isUndefined(value) {return typeof (value) === 'undefined';}export function isNaN(value) {return isNaN(value);}export function isBase64() {}export function isDate() { }export function isDate() { }export function isDate() { }export function isDate() { }export function isEqual(value, value2) {if (Object.is(value, value2)) return true;return JSON.stringify(value) === JSON.stringify(value2);}// Stringexport function trimAll(value) {return value.replace(/^[\s]+|[\s]+$/gm, '');}export function trimLeft(value) {return value.replace(/^[\s]+/gm, '');}export function trimRight(value) {return value.replace(/[\s]+$/gm, '');}export function decodeBase64(string) {let value = '';const input = string.replace(/[^A-Za-z0-9\+\/\=]/g, '');try {value = window.atob(input);} catch (e) {const chars = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12,'N': 13, 'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25,'a': 26, 'b': 27, 'c': 28, 'd': 29, 'e': 30, 'f': 31, 'g': 32, 'h': 33, 'i': 34, 'j': 35, 'k': 36, 'l': 37, 'm': 38,'n': 39, 'o': 40, 'p': 41, 'q': 42, 'r': 43, 's': 44, 't': 45, 'u': 46, 'v': 47, 'w': 48, 'x': 49, 'y': 50, 'z': 51,'0': 52, '1': 53, '2': 54, '3': 55, '4': 56, '5': 57, '6': 58, '7': 59, '8': 60, '9': 61, '+': 62, '/': 63, '=': 64};let chr1, chr2, chr3;let enc1, enc2, enc3, enc4;let i = 0;let j = input.length;while (i < j) {enc1 = chars[input.charAt(i++)];enc2 = chars[input.charAt(i++)];enc3 = chars[input.charAt(i++)];enc4 = chars[input.charAt(i++)];chr1 = ((enc1 << 2) | (enc2 >> 4));chr2 = (((enc2 & 15) << 4) | (enc3 >> 2));chr3 = (((enc3 & 3) << 6) | enc4);value += String.fromCharCode(chr1);if (enc3 !== 64) {value += String.fromCharCode(chr2);}if (enc4 !== 64) {value += String.fromCharCode(chr3);}}}return decodeURIComponent(value);}export function encodeBase64(string) {// const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';const input = encodeURIComponent(string);let value = '';try {value = window.btoa(input);} catch (e) {const chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M','N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm','n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='];let chr1, chr2, chr3;let enc1, enc2, enc3, enc4;let i = 0;let j = input.length;while (i < j) {chr1 = input.charCodeAt(i++);chr2 = input.charCodeAt(i++);chr3 = input.charCodeAt(i++);enc1 = (chr1 >> 2);enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);enc4 = (chr3 & 63);if (isNaN(chr2)) {enc3 = enc4 = 64;} else if (isNaN(chr3)) {enc4 = 64;}value += (chars[enc1] + chars[enc2] + chars[enc3] + chars[enc4]);}}return value;}export function noop() {return true;}export function yymmdd(date, separator = '-') {var d = (date || new Date());var year = d.getFullYear();var month = d.getMonth() + 1; // getMonth() 从 0开始var day = d.getDate();return `${year}${separator}${padStart(month)}${separator}${padStart(day)}`}export function padStart(value, length = 2) {return String(value).padStart(length, 0);}export function normalize() {return {milliseconds: (ms % 1000),seconds: (Math.floor(ms / 1000) % 60),minutes: (Math.floor(ms / 1000 / 60) % 60),hours: (Math.floor(ms / 1000 / 60 / 60) % 24),days: (Math.floor(ms / 1000 / 60 / 60 / 24))}}
