666个JavaScript工具,解放你日常板砖的双手

目标整理666+JS工具。不定期持续更新中

1.返回数组中的最大值

1
2
3
4
// 将Math.max()与扩展运算符 (...) 结合使用以获取数组中的最大值。
const arrayMax = arr => Math.max(...arr);
const arr = [1,2,3,5];
console.log(arrayMax(arr)) //5

2.返回数组中的最小值

1
2
3
4
// 将Math.min()与扩展运算符 (...) 结合使用以获取数组中的最小值。
const arrayMin = arr => Math.min(...arr);
const arr = [1, 2, 3, 5];
console.log(arrayMin(arr)) //1

3.将数组块划分为指定大小的较小数组

1
2
3
4
5
6
// 使用Array.from()创建新的数组, 这符合将生成的区块数。使用Array.slice()将新数组的每个元素映射到size长度的区块。如果原始数组不能均匀拆分, 则最终的块将包含剩余的元素。
const chunk = (arr, size) => Array.from({
length: Math.ceil(arr.length / size)
}, (v, i) => arr.slice(i * size, i * size + size));
const arr = [1, 2, 3, 5];
console.log(chunk(arr,2)) //0: Array [ 1, 2 ],1: Array [ 3, 5 ],

4.从数组中移除 false 值

1
2
3
4
// 使用Array.filter()筛选出 false 值 (false、null、0、""、undefined和NaN).
const compact = arr => arr.filter(Boolean);
const arr = [false,null,0,"",undefined,NaN,1]
console.log(compact(arr)) //[ 1 ]

5.计算数组中值的出现次数

1
2
3
4
// 使用Array.reduce()在每次遇到数组中的特定值时递增计数器。
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a, 0);
const arr = [1,2,1,2,3,3,3,3];
console.log(countOccurrences(arr,3))//4

6.深拼合数组

1
2
3
4
// 使用递归。使用Array.concat()与空数组 ([]) 和跨页运算符 (...) 来拼合数组。递归拼合作为数组的每个元素。
const deepFlatten= arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
const arr = [1, 2, [1, 2, [1, 2, [2, 3]]]];
console.log(deepFlatten(arr)) // [ 1, 2, 1, 2, 1, 2, 2, 3 ]

7.返回两个数组之间的差异

1
2
3
4
5
6
7
8
9
// 从b创建Set, 然后使用Array.filter() on 只保留a b中不包含的值.
const difference = (a, b) => {
const s = new Set(b);
return a.filter(x => !s.has(x));
};
const arr = [1,2,3];
const arr2 = [2,3,4];
console.log(difference(arr,arr2))//[1]
console.log(difference(arr2,arr))//[4]

8.返回数组的所有不同值

1
2
3
4
// 使用 ES6 Set和...rest运算符放弃所有重复的值。
const distinctValuesOfArray = arr => [...new Set(arr)];
const arr = [1, 2, 3, 1, 2];
console.log(distinctValuesOfArray(arr)) // [ 1, 2, 3 ]

9.返回数组中的每个第 n 个元素

1
2
// 使用Array.filter()创建一个包含给定数组的每个第 n 个元素的新数组。
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);

10.筛选出数组中的非唯一值

1
2
// 对于只包含唯一值的数组, 请使用Array.filter()。
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) !== arr.lastIndexOf(i));

11.拼合数组

1
2
3
// 使用Array.reduce()获取数组中的所有元素和concat()以拼合它们
const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
const flatten = [...a, ...v];

12.将数组向上拼合到指定深度

1
2
// 使用递归, 递减depth, 每层深度为1。使用Array.reduce()和Array.concat()来合并元素或数组。基本情况下, 对于等于1的depth停止递归。省略第二个元素,depth仅拼合到1的深度 (单个拼合)。
falttenDepth: (arr, depth = 1) => depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), []) : arr.reduce((a, v) => a.concat(v), []),

13.根据给定函数对数组元素进行分组

1
2
// 使用递归, 递减depth, 每层深度为1。使用Array.reduce()和Array.concat()来合并元素或数组。基本情况下, 对于等于1的depth停止递归。省略第二个元素,depth仅拼合到1的深度 (单个拼合)。
falttenDepth: (arr, depth = 1) => depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), []) : arr.reduce((a, v) => a.concat(v), [])

14.返回列表的头

1
2
3
// 使用arr[0]可返回传递的数组的第一个元素。
let head = arr => arr[0];
head = arr.shift();

15.返回除最后一个数组之外的所有元素

1
2
// 使用 "arr.slice(0,-1)" 返回数组的最后一个元素。
const initial = arr => arr.slice(0, -1);

16.初始化并填充具有指定值的数组

1
2
3
// 使用Array(n)创建所需长度的数组,fill(v)以填充所需的值。可以省略value以使用默认值0.
const initializeArrayWithRange = (end, start = 0) => Array.from({length: end - start }).map((v, i) => i + start);
const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);

17.返回两个数组中存在的元素的列表

1
2
// 从b创建Set, 然后使用Array.filter()on a只保留b中包含的值.
const intersection = (a, b) => a.filter(x => new Set(b).has(x));

18.返回数组中的最后一个元素

1
2
3
4
// 使用arr.length - 1可计算给定数组的最后一个元素的索引并返回它
let last = arr => arr[arr.length - 1];
last = arr.slice(-1);
last = arr.pop();

19.使用函数将数组的值映射到对象, 其中键值对由原始值作为键和映射值组成

1
2
3
// 使用匿名内部函数范围来声明未定义的内存空间, 使用闭包来存储返回值。使用新的Array可将该数组与函数的映射放在其数据集上, 而逗号运算符返回第二个步骤, 而不需要从一个上下文移动到另一个环境 (由于关闭和操作顺序)。
const mapObject = (arr, fn) => (a => (a = [arr, arr.map(fn)], a[0].reduce((acc, val, ind) => (acc[val] = a[1][ind], acc), {})))
();

20nthElement: 返回数组的第 n 个元素

1
2
// 使用Array.slice()可获取包含第 n 个元素的数组。如果索引超出界限, 则返回[]。省略第二个参数n, 以获取数组的第一个元素
const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];

21.从对象中选取对应于给定键的键值对

1
2
// 使用Array.reduce()将筛选/选取的密钥转换回具有相应键值对的对象 (如果在 obj 中存在该键)。
const pick = (obj, arr) => arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});

22.对原始数组进行变异, 以筛选出指定的值

1
2
3
4
5
6
// 使用Array.filter()和Array.includes()来拉出不需要的值。使用Array.length = 0可将传入的数组中的长度重置为零, 并将其设置为Array.push(), 以便仅使用所提取的值填充它。
const pull = (arr, ...args) => {
let pulled = arr.filter((v, i) => !args.includes(v));
arr.length = 0;
pulled.forEach(v => arr.push(v));
};

23.从数组中移除给定函数返回false的元素

1
2
3
4
5
//  使用Array.filter()查找返回 truthy 值的数组元素和Array.reduce()以使用Array.splice()删除元素。使用三参数 (func value, index, array调用函数).
const remove = (arr, func) => Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
arr.splice(arr.indexOf(val), 1);
return acc.concat(val);
}, []) : [];

24.返回数组中的随机元素

1
2
// 使用Math.random()生成一个随机数, 将它与length相乘, 并使用数学将其舍入到最接近的整数Math.floor()。此方法也适用于字符串
const sample = arr => arr[Math.floor(Math.random() * arr.length)];

25.随机数组值的顺序

1
2
// 使用Array.sort()可在比较器中使用Math.random()重新排序元素。
const shuffle = arr => arr.sort(() => Math.random() - 0.5);

26.返回数组中包含某元素的数组

1
2
// 从每个数组创建一个Set, 然后对它们中的每一个都使用Array.filter(), 以便只保留其他值中不包含的数值。
const similarity = (arr, values) => arr.filter(v => values.includes(v));

27.返回两个数组之间的对称差(通俗可以理解交接的反义词)

1
2
// 从每个数组创建一个Set, 然后对它们中的每一个都使用Array.filter(), 以便只保留其他值中不包含的数值。
const symmetricDifference = (a, b) => [...a.filter(x => !new Set(b).has(x)), ...b.filter(x => !new Set(a).has(x))];

28.返回数组(除第一个)中的所有元素

1
2
// 如果数组的length大于1, 则返回arr.slice(1), 否则返回整个数组。
const tail = arr => arr.length > 1 ? arr.slice(1) : arr;

29.返回一个数组(0-n)

1
2
// 使用Array.slice()创建数组的切片, 其中包含从开始处取出的n元素
const take = (arr, n = 1) => arr.slice(0, n);

30.返回一个数组(从第n个开始)

1
2
// 使用Array.slice()创建数组的切片, 其中包含从末尾取出的n元素
const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);

31.返回在两个数组(并集)元素

1
2
// 创建一个Set, 其中包含a和b的所有值, 并将其转换为数组。
const union = (a, b) => Array.from(new Set([...a, ...b]));

32.筛选出数组中包含指定值之一的元素

1
2
// 使用Array.filter()创建不包括的数组 (使用!Array.includes()) 所有给定值。
const without = (arr, ...args) => arr.filter(v => !args.includes(v));

33.创建基于原始数组中的位置分组的元素数组

1
2
3
4
5
6
7
8
9
10
11
// 使用Math.max.apply()获取参数中最长的数组。创建一个以该长度为返回值的数组, 并使用 map 函数创建一个分组元素的数组Array.from()如果参数数组的长度不同, 则在未找到任何值的情况下使用undefined。
const zip = (...arrays) => {
const maxLength = Math.max(...arrays.map(x => x.length));
return Array.from({
length: maxLength
}).map((_, i) => {
return Array.from({
length: arrays.length
}, (_, k) => arrays[k][i]);
})
};

34.数组中删除指定一项

1
2
3
4
5
6
7
8
9
10
11
const removeArrayItem = (arr, item) => {
var i = 0;
while (i < arr.length) {
if (arr[i] == item) {
arr.splice(i, 1);
} else {
i++;
}
}
return arr;
};

35.检查给定数组中是否包含某项

1
2
3
4
5
6
7
8
9
10
11
// 检查给定数组中是否包含某
let contains = (arr, item) => {
var i = arr.length;
while (i--) {
if (arr[i] === item) {
return true;
}
}
return false;
};
contains = (arr, item, key) => arr.map(i => (key ? i[key] : i) === item)?.length ? true : false

44.返回当前url

1
const currentURL = () => window.location.href;

45.获取url参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let getUrlParam = (name, origin = null) => {
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
let r = null;
if (origin == null) {
r = window.location.search.substr(1).match(reg);
} else {
r = origin.substr(1).match(reg);
}
if (r != null) return decodeURIComponent(r[2]);
return null;
}

getUrlParam = (name, origin = null) => {
let url = location.href;
let temp1 = url.split('?');
let pram = temp1[1];
let keyValue = pram.split('&');
let obj = {};
for (let i = 0; i < keyValue.length; i++) {
let item = keyValue[i].split('=');
let key = item[0];
let value = item[1];
obj[key] = value;
}
return obj[name];
}

46.修改url中的参数

1
2
3
4
5
6
const replaceParamVal = (paramName,replaceWith) => {
var oUrl = location.href.toString();
var re=eval('/('+ paramName+'=)([^&]*)/gi');
location.href = oUrl.replace(re,paramName+'='+replaceWith);
return location.href;
}

47.获取窗口可视范围的高度

1
2
3
4
5
6
7
8
9
10
const getClientHeight = () => {
let clientHeight = 0;
if (document.body.clientHeight && document.documentElement.clientHeight) {
clientHeight = (document.body.clientHeight < document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
}
else {
clientHeight = (document.body.clientHeight > document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
}
return clientHeight;
}

48.获取窗口可视范围宽度

1
2
3
4
5
const getPageViewWidth = () => {
let d = document,
a = d.compatMode == "BackCompat" ? d.body : d.documentElement;
return a.clientWidth;
}

49.获取窗口宽度

1
2
3
4
5
6
7
const getPageWidth = () => {
let g = document,
a = g.body,
f = g.documentElement,
d = g.compatMode == "BackCompat" ? a : g.documentElement;
return Math.max(f.scrollWidth, a.scrollWidth, d.clientWidth);
}

50.获取窗口尺寸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const getViewportOffset = () => {
if (window.innerWidth) {
return {
w: window.innerWidth,
h: window.innerHeight
}
} else {
// ie8及其以下
if (document.compatMode === "BackCompat") {
// 怪异模式
return {
w: document.body.clientWidth,
h: document.body.clientHeight
}
} else {
// 标准模式
return {
w: document.documentElement.clientWidth,
h: document.documentElement.clientHeight
}
}
}
}

50.获取滚动条距顶部高度

1
const getPageScrollTop = () => document.documentElement.scrollTop || document.body.scrollTop

51.获取滚动条距左边的高度

1
const getPageScrollLeft = () => document.documentElement.scrollLeft  || document.body.scrollLeft 

52.全屏开启/关闭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 开启
const launchFullscreen = () => {
if (element.requestFullscreen) {
element.requestFullscreen()
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen()
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen()
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullScreen()
}
}

# 关闭
const exitFullscreen = () => {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.msExitFullscreen) {
document.msExitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen()
}
}

53.当前滚动条位置

1
const getScrollPosition = (el = window) => {x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop }

54.滚动到指定元素区域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const smoothScroll = element =>{
document.querySelector(element).scrollIntoView({
behavior: 'smooth'
});
}

# 平滑滚动到页面顶部
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
}

55.http跳转https

1
const httpsRedirect = () => location.protocol !== 'https:' && location.replace('https://' + location.href.split('//')[1])

56.检查页面底部是否可见

1
const bottomVisible = () => document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight)

57.打开一个窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const openWindow(url, windowName, width, height) => {
const x = parseInt(screen.width / 2.0) - width / 2.0;
const y = parseInt(screen.height / 2.0) - height / 2.0;
const isMSIE = navigator.appName == "Microsoft Internet Explorer";
if (isMSIE) {
let p = "resizable=1,location=no,scrollbars=no,width=";
p = p + width;
p = p + ",height=";
p = p + height;
p = p + ",left=";
p = p + x;
p = p + ",top=";
p = p + y;
window.open(url, windowName, p);
} else {
let win = window.open(
url,
"ZyiisPopup",
"top=" +
y +
",left=" +
x +
",scrollbars=" +
scrollbars +
",dialog=yes,modal=yes,width=" +
width +
",height=" +
height +
",resizable=no"
);
eval("try { win.resizeTo(width, height); } catch(e) { }");
win.focus();
}
}

58.自适应页面(rem)

1
2
3
4
5
6
const AutoResponse = (width = 750) => {
const target = document.documentElement;
target.clientWidth >= 600
? (target.style.fontSize = "80px")
: (target.style.fontSize = target.clientWidth / width * 100 + "px");
}

59.截取字符串并加身略号

1
const subText = (str, length) => str?.length && str?.length > length ? str.substr(0, length) + "..." : str

60.获取文件base64编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* @param file
* @param format 指定文件格式
* @param size 指定文件大小(字节)
* @param formatMsg 格式错误提示
* @param sizeMsg 大小超出限制提示
* @returns {Promise<any>}
*/
const fileToBase64String = (file, format = ['jpg', 'jpeg', 'png', 'gif'], size = 20 * 1024 * 1024, formatMsg = '文件格式不正确', sizeMsg = '文件大小超出限制') => {
return new Promise((resolve, reject) => {
// 格式过滤
let suffix = file.type.split('/')[1].toLowerCase();
let inFormat = false;
for (let i = 0; i < format.length; i++) {
if (suffix === format[i]) {
inFormat = true;
break;
}
}
if (!inFormat) {
reject(formatMsg);
}
// 大小过滤
if (file.size > size) {
reject(sizeMsg);
}
// 转base64字符串
let fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
let res = fileReader.result;
resolve({base64String: res, suffix: suffix});
reject('异常文件,请重新选择');
}
})
}

61.B转换到KB,MB,GB并保留两位小数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @param { number } fileSize
*/
const formatFileSize = fileSize => {
let temp;
if (fileSize < 1024) {
return fileSize + 'B';
} else if (fileSize < (1024 * 1024)) {
temp = fileSize / 1024;
temp = temp.toFixed(2);
return temp + 'KB';
} else if (fileSize < (1024 * 1024 * 1024)) {
temp = fileSize / (1024 * 1024);
temp = temp.toFixed(2);
return temp + 'MB';
} else {
temp = fileSize / (1024 * 1024 * 1024);
temp = temp.toFixed(2);
return temp + 'GB';
}
}

62.base64转file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @param { base64 } base64
* @param { string } filename 转换后的文件名
*/
const base64ToFile = (base64, filename )=> {
let arr = base64.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let suffix = mime.split('/')[1] ;// 图片后缀
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, { type: mime })
};

63.base64转blob

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @param { base64 } base64
*/
const base64ToBlob = base64 => {
let arr = base64.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
};

64.blob转file

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

65.file转base64

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

66.递归生成树形结构

1
2
3
4
5
6
7
8
9
10
11
const 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;
}

67.遍历树节点

1
2
3
4
5
6
7
8
const 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);
}
}
}

68.寻找所有子节点

1
2
3
4
5
6
7
8
9
10
const 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;
}

69.根据pid生成树形结构

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* @param { string } osVersion
*/
const 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"
}
}

72.判断手机是Andoird还是IOS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 0: ios
* 1: android
* 2: 其它
*/
const 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;
}

73.函数防抖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* @param { function } func

* @param { number } wait 延迟执行毫秒数

* @param { boolean } immediate true 表立即执行,false 表非立即执行
*/
const 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);
}

}
}

74.函数节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* @param { function } func 函数

* @param { number } wait 延迟执行毫秒数

* @param { number } type 1 表时间戳版,2 表定时器版
*/
const 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)
}
}
}
}

75.生成指定范围随机数

1
const RandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min

76.数组乱序

1
2
3
4
5
6
7
8
9
10
11
12
const 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
}

77.数组交集

1
const similarity = (arr1, arr2) => arr1.filter(v => arr2.includes(v))

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

1
2
3
4
5
6
7
const 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
}

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

1
2
3
4
5
6
7
8
const 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));
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const 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);
}

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

1
2
3
4
5
6
const 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);
}

81.递归优化(尾递归)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* @param { function } f
*/
const 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;
}
}
}

82.生成随机整数

1
2
3
4
5
6
7
8
9
10
const 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
}
}

83.去除空格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* @param { string } str 待处理字符串
* @param { number } type 去除空格类型 1-所有空格 2-前后空格 3-前空格 4-后空格 默认为1
*/
const 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;
}
}

84.大小写转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @param { string } str 待转换的字符串
* @param { number } type 1-全大写 2-全小写 3-首字母大写 其他-不转换
*/

const 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;
}
}

85.随机16进制颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* hexColor 方法一
*/
const 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;
}
/**
* 方法二
*/
const randomHexColorCode = () => `#${(Math.random() * 0xfffff * 1000000).toString(16).slice(0, 6)}`;

86.转义html(防XSS攻击)

1
const escapeHTML = str => str.replace(/[&<>'"]/g, tag => ({'&': '&amp;','<': '&lt;','>': '&gt;',"'": '&#39;','"': '&quot;' }[tag] || tag) )

87.检测移动/PC设备

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

88.隐藏所有指定标签

1
const hideTag = (...el) => [...el].forEach(e => (e.style.display = 'none'))

89.查是否包含子元素

1
const elementContains = (parent, child) => parent !== child && parent.contains(child)

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

1
2
3
4
5
/**
* @param { number } val 输入的数字
* @param { number } maxNum 数字规定界限
*/
const outOfNum = (val, maxNum) => val && val > maxNum ? `${maxNum}+` : val

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

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

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

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

93.如何切换一个元素的类

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

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

1
2
3
4
5
const elementContains = (parent, child) => parent !== child && parent.contains(child);

// 事例
elementContains(document.querySelector('head'), document.querySelector('title')); // true
elementContains(document.querySelector('body'), document.querySelector('body')); // false

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

1
2
3
4
5
6
7
8
9
10
11
12
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); // 需要全屏(上下左右)可以见

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

1
2
3
4
5
6
7
8
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', '...']

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

1
2
3
4
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' }

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

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

99.如何在等待指定时间后调用提供的函数(sleep、delay)

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const triggerEvent = (el, eventType, detail) =>
el.dispatchEvent(new CustomEvent(eventType, { detail }));

// 事例
triggerEvent(document.getElementById('myId'), 'click');
triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' });
自定义事件的函数有 EventCustomEvent 和 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 listener
obj.addEventListener("cat", function(e) { process(e.detail) });

// create and dispatch the event
var 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" ] );
});

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

1
2
3
4
5
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);

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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'

103.如何获得两个日期之间的差异

1
2
3
4
5
// 以天为单位
const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
(dateFinal - dateInitial) / (1000 * 3600 * 24);
// 事例
getDaysDiffBetweenDates(new Date('2017-12-13'), new Date('2017-12-22')); // 9

104.如何对传递的URL发出请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// GET
const httpGet = (url, callback, err = console.error) => {
const request = new XMLHttpRequest();
request.open('GET', url, true);
request.onload = () => callback(request.responseText);
request.onerror = () => err(request);
request.send();
};

httpGet(
'https://lancema.com/posts/1',
console.log
);

// {"userId": 1, "id": 1, "title": "sample title", "body": "my text"}

// POST
const httpPost = (url, data, callback, err = console.error) => {
const request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
request.onload = () => callback(request.responseText);
request.onerror = () => err(request);
request.send(data);
};

const newPost = {
userId: 1,
id: 1337,
title: 'Foo',
body: 'bar bar bar'
};
const data = JSON.stringify(newPost);
httpPost(
'https://lancema.com/posts',
data,
console.log
);

// {"userId": 1, "id": 1337, "title": "Foo", "body": "bar bar bar"}

105.如何为指定选择器创建具有指定范围,步长和持续时间的计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const counter = (selector, start, end, step = 1, duration = 2000) => {
let current = start,
_step = (end - start) * step < 0 ? -step : step,
timer = setInterval(() => {
current += _step;
document.querySelector(selector).innerHTML = current;
if (current >= end) document.querySelector(selector).innerHTML = end;
if (current >= end) clearInterval(timer);
}, Math.abs(Math.floor(duration / (end - start))));
return timer;
};

// 事例
counter('#my-id', 1, 1000, 5, 2000);
// 让 `id=“my-id”`的元素创建一个2秒计时器

106.如何将字符串复制到剪贴板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
const selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
el.select();
document.execCommand('copy');
document.body.removeChild(el);
if (selected) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
};
// 事例
copyToClipboard('Lorem ipsum');
// 'Lorem ipsum' copied to clipboard

107.如何确定页面的浏览器选项卡是否聚焦

1
2
3
4
const isBrowserTabFocused = () => !document.hidden;

// 事例
isBrowserTabFocused(); // true

108.如何创建目录(如果不存在)

1
2
3
4
5
6
const fs = require('fs');
const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);

// 事例
createDirIfNotExists('test');
// 这里面的方法大都挺实用,可以解决很多开发过程问题,大家就好好利用起来吧。

109.日期型函数封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
const formatTime = date => {
if(!!date){
if(!(date instanceof Date))
date = new Date(date);
var month = date.getMonth() + 1
var day = date.getDate()
return `${month}${day}日`;
}
}

const formatDay = date => {
if(!!date){
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
return [year, month, day].map(formatNumber).join('-');
}
}

const formatDay2 = date => {
if(!!date){
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
return [year, month, day].map(formatNumber).join('/');
}
}

const formatWeek = date => {
if(!!date){
var day = date.getDay();
switch (day) {
case 0:
return '周日'
break;
case 1:
return '周一'
break;
case 2:
return '周二'
break;
case 3:
return '周三'
break;
case 4:
return '周四'
break;
case 5:
return '周五'
break;
case 6:
return '周六'
break;
}
}
}

const formatHour = date => {
if(!!date){
var hour = new Date(date).getHours();
var minute = new Date(date).getMinutes();
return [hour, minute].map(formatNumber).join(':');
}
}

const timestamp = (date, divisor = 1000) => {
if(date == undefined){
return;
}else if(typeof date == 'number'){
return Math.floor(date/divisor);
}else if(typeof date == 'string'){
var strs = date.split(/[^0-9]/);
return Math.floor(+new Date(strs[0] || 0,(strs[1] || 0)-1,strs[2] || 0,strs[3] || 0,strs[4] || 0,strs[5] || 0)/divisor);
}else if(Date.prototype.isPrototypeOf(date)){
return Math.floor(+date/divisor);
}
}

const detimestamp = date => {
if(!!date){
return new Date(date*1000);
}
}

const formatNumber = n => {//给在0-9的日期加上0
n = n.toString()
return n[1] ? n : '0' + n
}

110.时间戳转时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 时间戳转化为年 月 日 时 分 秒
* number: 传入时间戳
* format:返回格式,支持自定义,但参数必须与formateArr里保持一致
*/
const formatTime (number,format) => {
var formateArr = ['Y','M','D','h','m','s'];
var returnArr = [];

var date = new Date(number * 1000);
returnArr.push(date.getFullYear());
returnArr.push(formatNumber(date.getMonth() + 1));
returnArr.push(formatNumber(date.getDate()));
returnArr.push(formatNumber(date.getHours()));
returnArr.push(formatNumber(date.getMinutes()));
returnArr.push(formatNumber(date.getSeconds()));

for (var i in returnArr)
{
format = format.replace(formateArr[i], returnArr[i]);
}
return format;
}

//数据转化
const formatNumber n => {
n = n.toString()
return n[1] ? n : '0' + n
}

// 调用示例:
var sjc = 1488481383;//时间戳
console.log(time.formatTime(sjc,'Y/M/D h:m:s'));//转换为日期:2017/03/03 03:03:03
console.log(time.formatTime(sjc, 'h:m'));//转换为日期:03:03

111.格式化时间,转化为(几秒/分钟/小时/天) 前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 格式化时间,转化为几分钟前,几秒钟前
* @param timestamp 时间戳,单位是毫秒
*/
const timeFormat timestamp => {
var mistiming = Math.round((Date.now() - timestamp) / 1000);
var arrr = ['年', '个月', '星期', '天', '小时', '分钟', '秒'];
var arrn = [31536000, 2592000, 604800, 86400, 3600, 60, 1];
for (var i = 0; i < arrn.length; i++) {
var inm = Math.floor(mistiming / arrn[i]);
if (inm != 0) {
return inm + arrr[i] + '前';
}
}
}

112.获取n天之前的日期(10天前)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 获取n天之前的日期 getDaysBeforeDate(10) 10天前
* @param day 天数
*/
const getDaysBeforeDate = day => {
const date = new Date(),
timestamp, newDate;
timestamp = date.getTime();
// 获取三天前的日期
newDate = new Date(timestamp - day * 24 * 3600 * 1000);
const year = newDate.getFullYear();
// 月+1是因为js中月份是按0开始的
const month = newDate.getMonth() + 1;
const day = newDate.getDate();
if (day < 10) { // 如果日小于10,前面拼接0
day = '0' + day;
}
if (month < 10) { // 如果月小于10,前面拼接0
month = '0' + month;
}
return [year, month, day].join('/');
}

113.获取跳转的classId,通过hash方式获取

1
2
3
4
5
6
7
8
9
const getQueryString = () => {
var url= {},
a = '';
(a = window.location.search.substr(1)) || (a = window.location.hash.split('?')[1])
a.split(/&/g).forEach(function(item) {
url[(item = item.split('='))[0]] = item[1];
})
return url
}

114.过滤器指定字段

1
2
3
4
5
6
7
8
9
10
11
12
const filterArrBySex = (data, name) => {
if (!name) {
console.log(name)
return data;
} else {
return data.filter(function(ele, index, self) {
if (ele.name.includes(name)) {
return ele
}
})
}
}

115.根据身份证获数据(取出生年月/年龄)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 取出生年月
const getBirthdayFromIdCard = idCard => {
let birthday = "";
if (idCard != null && idCard != "") {
if (idCard.length == 15) {
birthday = "19" + idCard.substr(6, 6);
} else if (idCard.length == 18) {
birthday = idCard.substr(6, 8);
}
birthday = birthday.replace(/(.{4})(.{2})/, "$1-$2-");
}
return birthday;
}

const IdCard = UUserCard => {
//获取年龄
var myDate = new Date();
var month = myDate.getMonth() + 1;
var day = myDate.getDate();
var age = myDate.getFullYear() - UUserCard.substring(6, 10) - 1;
if (UUserCard.substring(10, 12) < month || UUserCard.substring(10, 12) == month && UUserCard.substring(12, 14) <= day) {
age++;
}
return age
}

116.原生js滑块验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//event.clientX:鼠标点下的点到左侧x轴的距离
window.onload = function() {
//事件处理 onmousedown onmousemove onmouseup
var box = document.querySelector(".box")
var btn = document.querySelector(".btn")
var bg = document.querySelector(".bg")
var text1 = document.querySelector(".text")
//封装的选择器 声明式函数可以提升
// function fun(){
//
// }
var flag = false; //标记
btn.onmousedown = function(event) {
var downx = event.clientX; //按下后获取的与x轴的距离
btn.onmousemove = function(e) {
var movex = e.clientX - downx; //滑块滑动的距离
//移动的范围
if (movex > 0) {
this.style.left = movex + "px";
bg.style.width = movex + "px";
if (movex >= box.offsetWidth - 40) {
//验证成功
flag = true
text1.innerHTML = "验证成功"
text1.style.color = "#fff"
//清除事件
btn.onmousedown = null;
btn.onmousemove = null;
}
}
}
}
//松开事件
btn.onmouseup = function() {
//清除事件
btn.onmousemove = null;
if (flag) return;
this.style.left = 0;
bg.style.width = 0 + "px";
}
}

117.js无限加载瀑布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//随机[m,n]之间的整数 封装
function randomNumber(m, n) {
return Math.floor(Math.random() * (n - m + 1) + m);
}
//随机颜色 封装
function randomColor() {
return "rgb(" + randomNumber(0, 255) + "," + randomNumber(0, 255) + "," + randomNumber(0, 255) + ")";
}

//获取当前的scrollTop
var scrollTopDistance;
//获取所有的ul
var uls = document.querySelectorAll("ul");
var i = 0;
var k = i;

const waterFall = () => {
for (i = k; i < k + 4; i++) {
//创建li
var li = document.createElement("li");
//随机颜色
li.style.backgroundColor = randomColor();
//随机高度
li.style.height = randomNumber(120, 400) + "px";
//手动转换为字符串
li.innerHTML = i + 1 + "";
//插入到对应的ul中
//判断哪个ul的高度低,该次创建的li就插入到此ul中
var index = 0; //记录下标
for (var j = 0; j < uls.length; j++) {
if (uls[j].offsetHeight < uls[index].offsetHeight) {
index = j;
}
}
//将元素节点插入文档中
uls[index].appendChild(li);
}
k = i;
return uls[index].offsetHeight;
}
waterFall();
//鼠标滚轮事件,由于右侧没有滚轮,所以使用onmousewheel事件
window.onmousewheel = function() {
//获取窗口的高度,要兼容浏览器
var windowH = document.documentElement.clientHeight;
//滚轮于top的距离,要兼容浏览器
var scrollH = document.documentElement.scrollTop ||
document.body.scrollTop;
//获取窗口的可见高度
var documentH = document.documentElement.scrollHeight ||
document.body.scrollHeight;
//窗口的高度 + 滚轮与顶部的距离 > 窗口的可见高度-200
if (windowH + scrollH > documentH - 200) {
//执行此函数
waterFall()
}
}

118.是否为外链

1
const isExternal = path => /^(https?:|mailto:|tel:)/.test(path)

119.数字且最多两位小数

1
const isNum = str => /^\d+(\.\d{1,2})?$/.test(str)

120.判断经纬度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**

* @description 判断经度 -180.0~+180.0(整数部分为0~180,必须输入1到5位小数)
* @param str
* @returns {boolean}
*/
const isLongitude = str => /^[-|+]?(0?\d{1,2}\.\d{1,5}|1[0-7]?\d{1}\.\d{1,5}|180\.0{1,5})$/.test(str)

/**

* @description 判断纬度 -90.0~+90.0(整数部分为0~90,必须输入1到5位小数)
* @param str
* @returns {boolean}
*/
const isLatitude = str => /^[-|+]?([0-8]?\d{1}\.\d{1,5}|90\.0{1,5})$/.test(str)

121.数组去重

1
2
3
4
5
6
7
8
9
10
11
// 方法一
let noRepeat = arr => [...new Set(arr)]
// 方法二
noRepeat = arr => Array.from(new Set(arr))
// 方法三
noRepeat = arr => arr.filter((v, idx) => idx == arr.lastIndexOf(v))
// 方法四
noRepeat = arr => Object.values(arr.reduce((s,n) => {
s[n] = n;
return s
},{}))

121.数组取值

1
2
3
4
5
6
// 最大值
const arrayMax = arr => Math.max(...arr)

// 最小值
const arrayMax = arr => Math.min(...arr)

121.扁平化

1
2
// 最大值
const flatten = (arr, depth = Infinity) => arr.flat(depth)

122.数组乱排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 洗牌算法
const shuffle = arr => {
let array = arr;
let index = array.length;

while (index) {
index -= 1;
let randomInedx = Math.floor(Math.random() * index);
let middleware = array[index];
array[index] = array[randomInedx];
array[randomInedx] = middleware;
}

return array;
}

// sort + random
shuffle = arr => arr.sort((n,m)=>Math.random() - .5)

123.数组乱排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 洗牌算法
const shuffle = arr => {
let array = arr;
let index = array.length;

while (index) {
index -= 1;
let randomInedx = Math.floor(Math.random() * index);
let middleware = array[index];
array[index] = array[randomInedx];
array[randomInedx] = middleware;
}

return array;
}

// sort + random
shuffle = arr => arr.sort((n,m)=>Math.random() - .5)