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
image.png

  1. yarn add collect.js

mathjs

https://github.com/josdejong/mathjs
https://mathjs.org/
image.png

sugarjs

sugarjs https://sugarjs.com/
image.png

lazy.js

https://github.com/dtao/lazy.js
http://danieltao.com/lazy.js/

  1. 函数调用
  2. // 冗余
  3. function test1() { console.log('test1'); };
  4. function test2() { console.log('test2'); };
  5. var test3 = 1;
  6. if (test3 == 1) { test1(); }
  7. else { test2(); }
  8. // 简单
  9. (test3 === 1? test1:test2)();
  10. 多行字符串
  11. // 冗余
  12. const data = 'abc abc abc abc abc abc\n\t'
  13. + 'test test,test test test test\n\t'
  14. // 简洁
  15. const data = `abc abc abc abc abc abc
  16. test test,test test test test`
  17. 隐式返回
  18. // 冗余
  19. function getArea(diameter) {
  20. return Math.PI * diameter
  21. }
  22. // 简洁
  23. getArea = diameter => (
  24. Math.PI * diameter;
  25. )
  26. 字符串重复多次
  27. // 冗余
  28. let test = '';
  29. for(let i = 0; i < 5; i ++) {
  30. test += 'test ';
  31. }
  32. // 简洁
  33. 'test '.repeat(5);
  34. 幂乘
  35. // 冗余
  36. Math.pow(2,3);
  37. // 简洁而
  38. 2**3 // 8
  39. 获取对象的key, value
  40. Object.keys()、Object.values()、Object.entries()的用法
  41. 图片懒加载
  42. 可以通过为图片文件添加loading="lazy"的属性来实现:
  43. ![](image.png)
  44. 数组去重
  45. 1.借助Set
  46. const arr = [12,34,565,12,34,1,3,1]
  47. const newArr = Array.from(new Set(arr))
  48. console.log('newArr',newArr);
  49. const numbers = [1,2,3,4,1,2,3,4];
  50. const result = [... new Set(numbers)];
  51. ?.链式合并运算
  52. // 错误写法,当某一层级值为null或undefined时,会报错
  53. const userName = list.info.base.userName;
  54. // 正确写法(我们常用的方式)
  55. const userName = (list && list.info && list.info.base &&
  56. list.info.base.userName) || 'userName'// 错误写法,当某一层级值为null或
  57. undefined时,会报错
  58. const userName = list.info.base.userName;
  59. // 正确写法(我们常用的方式)
  60. const userName = (list && list.info && list.info.base &&
  61. list.info.base.userName) || 'userName'
  62. es2020引入链合并运算符,简化上面的写法
  63. const userName = list?.info?.base?.userName || 'userName';
  64. ?.运算符这在有时候处理对象时非常有用,看下面案例,person.name返回undefined然后在调用toString这时肯定会报错,
  65. 这时使用?.运算符就不会产生错误,?.运算符是只有在当值不是undefined时才会调用toString方法。
  66. 双位运算符
  67. 双位运算符比Math.floor(),Math.ceil()速度快
  68. `~~7.5 // 7
  69. Math.ceil(7.5) // 8
  70. Math.floor(7.5) // 7
  71. ~~-7.5 // -7
  72. Math.floor(-7.5) // -8
  73. Math.ceil(-7.5) // -7
  74. ~~双非运算符
  75. ~~双非运算符可以用于向下取整
  76. console.log(~~4.3) // 4
  77. ??运算符只有前面的值是undefined or null才会执行,工作中有的情况下使用,我们来看一下。
  78. let status = undefined;
  79. let text = status ?? "暂无"
  80. console.log(text) // 暂无
  81. ??的意思是 如果?? 左边的值是null 或者是undefined,那么就返回右边的
  82. const height = 0
  83. console.log(height||100)//100
  84. cosole.log(height ?? 100)//0
  85. 检查数值是不是NAN
  86. Number.isNaN(1+NaN); // true; NaN 数值与非数值运算的结果NaN
  87. 深度 clone
  88. const objectA = {a: 1, b: 2};
  89. const clonedA = JSON.parse(JSON.stringify(objectA));
  90. 字符串转数字
  91. let numberStr = "123";
  92. +numberStr; // 123
  93. numberStr = '123.12';
  94. +numberStr; // 123.12
  95. 数字转字符串
  96. 直接在需要转换的数字后加上空字符串,最快捷的转换,比调用toString快很多
  97. 判断正负值
  98. // Math.sign()
  99. // 判断正负, 还是0; 对非数值,能转化的转化; 不能转的就是NaN
  100. // 返回值: 正 +1; 负 -1; 0; 0; 其他值 NaN
  101. Array.of(传一组数值); 用于将一组值,转换为数组
  102. Array.from(param1, param2)方法用于将两类对象转为真正的数组
  103. 参数1: 一个对象 ==> 伪数组对象和可遍历(iterable)的对象
  104. 参数2: 回调函数 ==> 类似于数组的map方法,对每个元素进行处理,将处理后的值放入返回的数组。
  105. return值: 一个数组;
  106. 示例:
  107. let arrayLike = {
  108. '0': 'a',
  109. '1': 'b',
  110. '2': 'c',
  111. length: 3
  112. // 0: 'a',
  113. // 1: 'b',
  114. // 2: 'c',
  115. // length: 3
  116. };
  117. let real_arr = Array.from(arrayLike);
  118. 在两个数组匹配取值的情况,如果嵌套循环,效率低,并且代码看着不美观。利用对象的特性,可以简化复杂度。例如根据id匹配员工工资
  119. 双数组匹配
  120. const employees = [
  121. {id: 1, name: 'Tom'},
  122. {id: 2, name: 'Jerry'},
  123. {id: 3, name: 'Jim'},
  124. {id: 4, name: 'Kate'}
  125. ];
  126. const salary = [
  127. {id: 1, salary: 10000},
  128. {id: 2, salary: 20000},
  129. {id: 3, salary: 30000},
  130. {id: 4, salary: 40000}
  131. ];
  132. const salaryObj = {};
  133. salary.map(({id, salary}) => salaryObj[id] = salary);
  134. employees.map(e => e.salary = salaryObj[e.id]);
  135. JavaScript 中只有六个虚值
  136. undefined
  137. null
  138. NaN
  139. 0
  140. "" (空字符串)
  141. false
  142. myArray.filter(Boolean);
  143. 去除当前数组里的false值
  144. # !!
  145. !!0; // false
  146. !!undefined; // false
  147. !!null; // false
  148. !!(()=>{}); // true
  149. 原始的 myArray 会保持不变
  150. myArray
  151. .map(item => {
  152. // Do your changes and return the new item
  153. })
  154. .filter(Boolean);
  155. 合并多个对象
  156. const user = {
  157. name: 'John Ludwig',
  158. gender: 'Male'
  159. };
  160. const college = {
  161. primary: 'Mani Primary School',
  162. secondary: 'Lass Secondary School'
  163. };
  164. const skills = {
  165. programming: 'Extreme',
  166. swimming: 'Average',
  167. sleeping: 'Pro'
  168. };
  169. const summary = {...user, ...college, ...skills};
  170. 数组排序
  171. 默认情况下 sort 方法把数组元素转换为字符串,并对其进行字典排序。在对数字数组进行排序时,这有可能会导致一些问题
  172. [0,10,4,9,123,54,1].sort((a,b) => a-b);
  173. [0, 1, 4, 9, 10, 54, 123]
  174. 阻止用户在你的网页上单击鼠标右键
  175. <body oncontextmenu="return false">
  176. <div></div>
  177. </body>
  178. 获取数组中的最后一项
  179. 过对 splice 方法的参数传入负整数,来数获取组末尾的元素
  180. let array = [0, 1, 2, 3, 4, 5, 6, 7]
  181. console.log(array.slice(-1));
  182. [7]
  183. console.log(array.slice(-2));
  184. [6, 7]
  185. console.log(array.slice(-3));
  186. [5, 6, 7]
  187. Promise.all 的主要注意事项是,当一个 Promise 拒绝时,该方法将引发错误。这意味着你的代码不会等到你所有的 promise 都完成
  188. 等到所有 promise 都完成后,无论它们被拒绝还是被解决,都可以使用 Promise.allSettled。此方法在 ES2020 的最终版本得到支持
  189. 即使某些 promise 被拒绝,Promise.allSettled 也会从你所有的 promise 中返回结果
  190. const PromiseArray = [
  191. Promise.resolve(100),
  192. Promise.reject(null),
  193. Promise.resolve("Data release"),
  194. Promise.reject(new Error('Something went wrong'))];
  195. Promise.allSettled(PromiseArray).then(res =>{
  196. console.log(res);
  197. }).catch(err => console.log(err));
  198. //[
  199. //{status: "fulfilled", value: 100},
  200. //{status: "rejected", reason: null},
  201. //{status: "fulfilled", value: "Data release"},
  202. //{status: "rejected", reason: Error: Something went wrong ...}
  203. //]
  204. try..catch..finally
  205. const getData = async () => {
  206. try {
  207. setLoading(true);
  208. const response = await fetch(
  209. "https://jsonplaceholder.typicode.com/posts"
  210. );
  211. const data = await response.json();
  212. setData(data);
  213. } catch (error) {
  214. console.log(error);
  215. setToastMessage(error);
  216. } finally {
  217. setLoading(false); // 不管是否报错,最后都会执行
  218. }
  219. };
  220. getData();
  221. 别名结构赋值
  222. const object = { number: 10 };
  223. // Grabbing number
  224. const { number } = object;
  225. // Grabbing number and renaming it as otherNumber
  226. const { number: otherNumber } = object;
  227. console.log(otherNumber); //10
  228. eval 生成正则表达式,动态正则匹配
  229. let str = 'hello world ';
  230. let reg1 = `/hello/g`;
  231. let reg2 = `/world/g`;
  232. eval(reg1).test(str); // true
  233. eval(reg2).test(str); // true

Form表单

String字符串

https://github.com/jprichardson/string.js

文本选中

https://github.com/EvandroLG/selecting

  1. npm install selecting

image.png

音频&视频

图片相关

轮播图

https://github.com/sachinchoolur/lightgallery.js
image.png
https://github.com/fengyuanchen/cropperjs

https://fengyuanchen.github.io/viewerjs/
image.png

图片懒加载

https://github.com/dinbror/blazy/
https://dinbror.dk/blazy/?ref=github
image.png

JS数据可视化

  • d3.js
  • three.js
  • echarts.js

BOM操作

domurl

https://github.com/Mikhus/domurl

  1. npm install domurl

urijs

  1. import URI from 'urijs'

禁止页面另存为:标签加入以下代码

  1. <noscript>
  2. <iframe src=”*.htm”></iframe>
  3. </noscript>

禁止复制页面内容

  1. <body
  2. οncοntextmenu=”return false” 禁止鼠标右键菜单
  3. onselectstart=”return false” 禁止鼠标选取
  4. οndragstart=”return false” 禁止鼠标拖拽
  5. >
  6. </body>

html encode & decode

https://github.com/mathiasbynens/he

原生JS的重要性

你不需要 lodash

你不需要 Jquery

  1. function loop(array, fn){
  2. for ( var i = 0; i < array.length; i++ )
  3. fn.call( array, array[i], i );
  4. }
  5. // 最小值
  6. function smallest(array){
  7. return Math.min.apply( Math, array );
  8. }
  9. // 最大值
  10. function largest(array){
  11. return Math.max.apply( Math, array );
  12. }
  13. // sleep
  14. const sleep = ms => new Promise(resolve => setTimeout(() => resolve(), ms))
  15. /**
  16. * 函数防抖
  17. * @params callback 回调函数
  18. * @param wait 延迟执行毫秒数
  19. * @param immediate true 表立即执行,false 表非立即执行
  20. */
  21. function debounce(callback, wait, immediate) {
  22. let timeout
  23. return function() {
  24. let _this = this
  25. let args = arguments // arguments 必须在函数内部是用
  26. if(timeout) clearTimeout(timeout)
  27. if(immediate) {
  28. const callNow = !timeout
  29. timeout = setTimeout(() => {
  30. timeout = null
  31. }, wait)
  32. if(callNow) func.apply(_this, args)
  33. }
  34. else {
  35. timeout = setTimeout(() => {
  36. callback.apply(_this, args)
  37. }, wait)
  38. }
  39. }
  40. }
  41. // 函数节流
  42. // Returns a function, that, when invoked, will only be triggered at most once
  43. // during a given window of time. Normally, the throttled function will run
  44. // as much as it can, without ever going more than once per `wait` duration;
  45. // but if you'd like to disable the execution on the leading edge, pass
  46. // `{leading: false}`. To disable execution on the trailing edge, ditto.
  47. function throttle(func, wait, options) {
  48. var context, args, result;
  49. var timeout = null;
  50. var previous = 0;
  51. if (!options) options = {};
  52. var later = function() {
  53. previous = options.leading === false ? 0 : Date.now();
  54. timeout = null;
  55. result = func.apply(context, args);
  56. if (!timeout) context = args = null;
  57. };
  58. return function() {
  59. var now = Date.now();
  60. if (!previous && options.leading === false) previous = now;
  61. var remaining = wait - (now - previous);
  62. context = this;
  63. args = arguments;
  64. if (remaining <= 0 || remaining > wait) {
  65. if (timeout) {
  66. clearTimeout(timeout);
  67. timeout = null;
  68. }
  69. previous = now;
  70. result = func.apply(context, args);
  71. if (!timeout) context = args = null;
  72. } else if (!timeout && options.trailing !== false) {
  73. timeout = setTimeout(later, remaining);
  74. }
  75. return result;
  76. };
  77. };
  78. // 数组去重的20中思路
  79. // setTimeout实现 setInterval
  80. function _setInterval(){
  81. let timer = setTimeout(() =>{
  82. _setInterval()
  83. clearTimeout(timer)
  84. }, 1000)
  85. }
  86. function myInterval(callback, time){
  87. function inner() {
  88. callback()
  89. setTimeout(inner, time)
  90. }
  91. inner()
  92. }
  93. // 闭包
  94. (function(){
  95. const utils = window._utils_ = function() {}
  96. })();
  97. const utils = (function(){
  98. function utils() {}
  99. })()
  100. Object.prototype.keys = function(){
  101. var keys = [];
  102. for ( var i in this )
  103. keys.push( i );
  104. return keys;
  105. }
  106. Function.prototype.bind = function(object){
  107. var fn = this;
  108. return function(){
  109. return fn.apply(object, arguments);
  110. };
  111. };
  112. // 生成26个字母
  113. Array.from({length: 26}, (_, i) => String.fromCharCode(65+i))

本地字典

dict.js

  1. // Badge 状态
  2. export const STATUS = {
  3. 0: { label: '在线', value: 'green' }, // 绿
  4. 1: { label: '故障', value: 'orange'}, // 橙
  5. 2: { label: '预警', value: 'yellow' }, // 黄
  6. 3: { label: '离线', value: 'default' }, // 灰
  7. }
  8. export const TIMESTAMP = {
  9. 'h1': () => datenow() - oneHour,
  10. 'h6': () => datenow() - oneHour * 6,
  11. 'h12':() => datenow() - oneHour * 12,
  12. 'day1':() => datenow() - oneDay,
  13. 'day3':() => datenow() - oneDay * 3,
  14. 'day7':() => datenow() - oneDay * 7,
  15. }
  1. // JSON转字符串
  2. export function JsonEncode(obj) {
  3. return JSON.stringify(obj);
  4. }
  5. // 字符串转JSON
  6. export function JsonDecode(str) {
  7. let value = '';
  8. try {
  9. value = JSON.parse(str);
  10. }
  11. catch(e) {
  12. // unquote 转义字符也会导致解析失败
  13. const newString = str.replace(/&quot;/g, '\"');
  14. value = JSON.parse(newString);
  15. }
  16. return value;
  17. }
  18. // 转义 url
  19. export function DecodeUri(string) {
  20. const { decodeURIComponent, escape } = window;
  21. return decodeURIComponent(escape(string));
  22. }
  23. // 字符串转JSON
  24. export function EncodeUri(string) {
  25. const { encodeURIComponent, unescape } = window;
  26. return unescape(encodeURIComponent(string));
  27. }
  28. // 获取 URL参数
  29. export function getParams() {
  30. const query = window.location.search.substr(1);
  31. const queryArray = query.split('&');
  32. return queryArray.reduce((prev, next) => {
  33. const [key, value] = next.split('=');
  34. prev[key] = value;
  35. return prev;
  36. }, {});
  37. }
  38. // 获取 URL参数,正则
  39. export function getParams() {
  40. const REG = /(([\w\-]+){1}(\=([^\&\n\r\t]*){1})?)/g;
  41. const query = REG.exec(window.location.search.substr(1));
  42. }
  43. export function getUrl() {
  44. return window.location.href;
  45. }
  46. export function isFile(url) {
  47. return url.includes('file://')
  48. }
  49. export function isHttp() {
  50. return url.includes('http://')
  51. }
  52. export function isHttps() {
  53. return url.includes('https://')
  54. }
  55. export function isLocalhost(url) {
  56. const reg = /^(https?\:\/\/)(localhost|127\.0\.0\.1)(\:[\d]+)?(\/(.)*)?$/;
  57. return reg.test(url);
  58. }
  59. // Number
  60. export function isFloat(value) {
  61. return value % 1 !== 0;
  62. }
  63. // type类型
  64. export function isDate(value) {
  65. return Object.prototype.toString.call(value) === '[object Date]';
  66. }
  67. export function isFunction(value) {
  68. return typeof (value) === 'function';
  69. }
  70. export function isArray(value) {
  71. if (Array.isArray) {
  72. return Array.isArray(value);
  73. }
  74. return (Object.prototype.toString.call(value) === '[object Array]');
  75. }
  76. export function isObject(value) {
  77. return Object.prototype.toString.call(value) === '[object Object]';
  78. }
  79. export function isBoolean() {
  80. return typeof (val) === 'boolean'
  81. }
  82. export function isError(value) {
  83. return value instanceof Error;
  84. }
  85. export function isNumber(value) {
  86. return typeof (value) === 'number' && !isNaN(value) && isFinite(value)
  87. }
  88. export function isNull() {
  89. // undefined, null
  90. return value == null;
  91. }
  92. export function isRegExp(value) {
  93. return value instanceof RegExp;
  94. }
  95. export function isString(value) {
  96. return typeof (value) === 'string';
  97. }
  98. export function isJSON(value) {
  99. if (!isString(value)) return false;
  100. try {
  101. const values = JSON.parse(value);
  102. return values !== null && typeof (values) === 'object';
  103. } catch (e) {
  104. return false;
  105. }
  106. }
  107. export function isBase64() {
  108. if (!isString(value) || value.trim() === '') return false;
  109. try {
  110. return btoa(atob(value)) == value;
  111. } catch (e) {
  112. return false;
  113. }
  114. }
  115. export function isUndefined(value) {
  116. return typeof (value) === 'undefined';
  117. }
  118. export function isNaN(value) {
  119. return isNaN(value);
  120. }
  121. export function isBase64() {
  122. }
  123. export function isDate() { }
  124. export function isDate() { }
  125. export function isDate() { }
  126. export function isDate() { }
  127. export function isEqual(value, value2) {
  128. if (Object.is(value, value2)) return true;
  129. return JSON.stringify(value) === JSON.stringify(value2);
  130. }
  131. // String
  132. export function trimAll(value) {
  133. return value.replace(/^[\s]+|[\s]+$/gm, '');
  134. }
  135. export function trimLeft(value) {
  136. return value.replace(/^[\s]+/gm, '');
  137. }
  138. export function trimRight(value) {
  139. return value.replace(/[\s]+$/gm, '');
  140. }
  141. export function decodeBase64(string) {
  142. let value = '';
  143. const input = string.replace(/[^A-Za-z0-9\+\/\=]/g, '');
  144. try {
  145. value = window.atob(input);
  146. } catch (e) {
  147. const chars = {
  148. '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,
  149. '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,
  150. '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,
  151. '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,
  152. '0': 52, '1': 53, '2': 54, '3': 55, '4': 56, '5': 57, '6': 58, '7': 59, '8': 60, '9': 61, '+': 62, '/': 63, '=': 64
  153. };
  154. let chr1, chr2, chr3;
  155. let enc1, enc2, enc3, enc4;
  156. let i = 0;
  157. let j = input.length;
  158. while (i < j) {
  159. enc1 = chars[input.charAt(i++)];
  160. enc2 = chars[input.charAt(i++)];
  161. enc3 = chars[input.charAt(i++)];
  162. enc4 = chars[input.charAt(i++)];
  163. chr1 = ((enc1 << 2) | (enc2 >> 4));
  164. chr2 = (((enc2 & 15) << 4) | (enc3 >> 2));
  165. chr3 = (((enc3 & 3) << 6) | enc4);
  166. value += String.fromCharCode(chr1);
  167. if (enc3 !== 64) {
  168. value += String.fromCharCode(chr2);
  169. }
  170. if (enc4 !== 64) {
  171. value += String.fromCharCode(chr3);
  172. }
  173. }
  174. }
  175. return decodeURIComponent(value);
  176. }
  177. export function encodeBase64(string) {
  178. // const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  179. const input = encodeURIComponent(string);
  180. let value = '';
  181. try {
  182. value = window.btoa(input);
  183. } catch (e) {
  184. const chars = [
  185. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  186. 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  187. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  188. 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  189. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='
  190. ];
  191. let chr1, chr2, chr3;
  192. let enc1, enc2, enc3, enc4;
  193. let i = 0;
  194. let j = input.length;
  195. while (i < j) {
  196. chr1 = input.charCodeAt(i++);
  197. chr2 = input.charCodeAt(i++);
  198. chr3 = input.charCodeAt(i++);
  199. enc1 = (chr1 >> 2);
  200. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  201. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  202. enc4 = (chr3 & 63);
  203. if (isNaN(chr2)) {
  204. enc3 = enc4 = 64;
  205. } else if (isNaN(chr3)) {
  206. enc4 = 64;
  207. }
  208. value += (chars[enc1] + chars[enc2] + chars[enc3] + chars[enc4]);
  209. }
  210. }
  211. return value;
  212. }
  213. export function noop() {
  214. return true;
  215. }
  216. export function yymmdd(date, separator = '-') {
  217. var d = (date || new Date());
  218. var year = d.getFullYear();
  219. var month = d.getMonth() + 1; // getMonth() 从 0开始
  220. var day = d.getDate();
  221. return `${year}${separator}${padStart(month)}${separator}${padStart(day)}`
  222. }
  223. export function padStart(value, length = 2) {
  224. return String(value).padStart(length, 0);
  225. }
  226. export function normalize() {
  227. return {
  228. milliseconds: (ms % 1000),
  229. seconds: (Math.floor(ms / 1000) % 60),
  230. minutes: (Math.floor(ms / 1000 / 60) % 60),
  231. hours: (Math.floor(ms / 1000 / 60 / 60) % 24),
  232. days: (Math.floor(ms / 1000 / 60 / 60 / 24))
  233. }
  234. }