这些JS工具函数够你用到2020年底了
前言
活不多说,自己平时搜集的干货函数奉上。
干货函数
视频全屏
// 全屏
function fullScreen(el) {
const isFullscreen =
document.fullScreen ||
document.mozFullScreen ||
document.webkitIsFullScreen;
if (!isFullscreen) {
//进入全屏,多重短路表达式
(el.requestFullscreen && el.requestFullscreen()) ||
(el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
(el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
(el.msRequestFullscreen && el.msRequestFullscreen());
} else {
//退出全屏,三目运算符
document.exitFullscreen
? document.exitFullscreen()
: document.mozCancelFullScreen
? document.mozCancelFullScreen()
: document.webkitExitFullscreen
? document.webkitExitFullscreen()
: "";
}
}
找出数字在数组中下一个相邻的元素
let i = "";
let rr = [];
const name = (n, arr1)=>{
let num = Number(n);
for (let i = 0; i < arr1.length; i++) {
const element = arr1[i];
if (element != num) {
rr.push(num--);
}
}
return rr.find((el) => {
let newel = String(el);
return arr1.includes(newel);
})}
let arr = ["2", "4", "6", "8", "10", "12", "14", "16", "18", "20", "22", "24", "27", "30", "33", "36", "42", "48", "54", "60"]
console.log(name('5',arr)); //4
格式化时间
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000
} else {
time = +time
}
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
)
}
}
解析时间
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
*/
function parseTime(time, cFormat) {
if (arguments.length === 0 || !time) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
// support "1548221490638"
time = parseInt(time)
} else {
// support safari
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
time = time.replace(new RegExp(/-/gm), '/')
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
return value.toString().padStart(2, '0')
})
return time_str
}
解析Url地址
/**
* @param {string} url
* @returns {Object}
*/
function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
合并两个对象
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
function objectMerge(target, source) {
if (typeof target !== 'object') {
target = {}
}
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
} else {
target[property] = sourceProperty
}
})
return target
}
数组去重
/**
* @param {Array} arr
* @returns {Array}
*/
function uniqueArr(arr) {
return Array.from(new Set(arr))
}
防抖
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
简易搜索
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="int">
</body>
<script>
let list = ["示例1","示例12","示例5","示例56"];
document.querySelector('#int').onchange=function(e){
console.log(search(e.target.value));
}
function search(val) {
if (val) {
return list.filter(function (item) {
return Object.keys(item).some(function (key) {
return String(item[key]).toLowerCase().indexOf(val) > -1
})
})
}
return list
}
</script>
</html>
将秒化为时分秒
function formateSeconds (endTime) {
let secondTime = parseInt(endTime); //将传入的秒的值转化为Number
let min = 0; // 初始化分
let h = 0; // 初始化小时
let result = "";
if (secondTime > 60) {
//如果秒数大于60,将秒数转换成整数
min = parseInt(secondTime / 60); //获取分钟,除以60取整数,得到整数分钟
secondTime = parseInt(secondTime % 60); //获取秒数,秒数取佘,得到整数秒数
if (min > 60) {
//如果分钟大于60,将分钟转换成小时
h = parseInt(min / 60); //获取小时,获取分钟除以60,得到整数小时
min = parseInt(min % 60); //获取小时后取佘的分,获取分钟除以60取佘的分
}
}
result = `${h.toString().padStart(2, "0")}:${min.toString().padStart(2, "0")}:${secondTime.toString().padStart(2, "0")}`;
return result;
}
将时分秒化为秒
function formSeconds (times) {
let arr = times.split(":");
let s = arr[2];
let m = arr[1];
let h = arr[0];
let m1 = m<10?m.replace(/\b(0+)/gi,""):m;
let h1 = h<10?h.replace(/\b(0+)/gi,""):h;
return m1*60+Number(h1)+Number(s)
}
对象深层遍历
var obj = {
a:{
b:{
c:"maomin"
}
}
}
const safeGet = (obj, path) => {
try {
return path.split('.').reduce((o, k) => o[k], obj)
} catch (e) {
return undefined
}
}
console.log(safeGet(obj,'a.b.c'));// maomin
带有分割符的字符串转化成一个n维数组
var str = "A-2-12";
var str1 = str.split('-');
var arr = str1.reverse().reduce((pre,cur,i) => {
if(i==0)
{ pre.push(cur)
return pre
}
return [cur,pre]
},[])
console.log(arr) // ["A"["B",["C"]]]
获取时间戳
function thedata(d){
return d.replace(/\-/g, "\/")
}
var serverTime = parseInt(new Date(thedata('2020-08-12 15:52:11')).valueOf());
console.log(serverTime); // 1597218731000,获取到时间戳
对象深拷贝
function deepClone(target) {
// 定义一个变量
let result;
// 如果当前需要深拷贝的是一个对象的话
if (typeof target === 'object') {
// 如果是一个数组的话
if (Array.isArray(target)) {
result = []; // 将result赋值为一个数组,并且执行遍历
for (let i in target) {
// 递归克隆数组中的每一项
result.push(deepClone(target[i]))
}
// 判断如果当前的值是null的话;直接赋值为null
} else if(target===null) {
result = null;
// 判断如果当前的值是一个RegExp对象的话,直接赋值
} else if(target.constructor===RegExp){
result = target;
}else {
// 否则是普通对象,直接for in循环,递归赋值对象的所有值
result = {};
for (let i in target) {
result[i] = deepClone(target[i]);
}
}
// 如果不是对象的话,就是基本数据类型,那么直接赋值
} else {
result = target;
}
// 返回最终结果
return result;
}
简易版对象拷贝
function copy(obj) {
if(typeof obj == "object") { //判断是否复杂类型
var result = obj.constructor == Array ? [] : {};//判断数组类型或是object,数组即result=[],object即result={}
for(let i in obj) {
result[i] = typeof obj[i] == "object" ? copy(obj[i]) : obj[i]//判断数据每一项是否是object
}
} else {
var result = obj //基本类型直接拷贝
}
return result;
}
实现一个模板引擎
function render(template, data) {
const reg = /\{\{(\w+)\}\}/; // 模板字符串正则
if (reg.test(template)) { // 判断模板里是否有模板字符串
const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
return render(template, data); // 递归的渲染并返回渲染后的结构
}
return template; // 如果模板没有模板字符串直接返回
}
let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
name: '姓名',
age: 18
}
render(template, data); // 我是姓名,年龄18,性别undefined
节流
// ①定时器实现
const throttle = (fn,delay = 500) =>{
let flag = true;
return (...args) => {
if(!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this,args);
flag = true;
},delay);
};
}
// ②时间戳实现
const throttle = (fn,delay = 500) => {
let preTime = Date.now();
return (...args) => {
const nowTime = Date.now();
if(nowTime - preTime >= delay){
preTime = Date.now();
fn.apply(this,args);
}
}
}
封装fetch
/**
* 封装fetch函数,用Promise做回调
* @type {{get: (function(*=)), post: (function(*=, *=))}}
*/
const fetchUtil = {
get: (url) => {
return new Promise((resolve, reject) => {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
}).then((response) => response.json()).then(response => {
resolve(response);
}).catch(err => {
reject(new Error(err));
});
});
},
post: (url, params) => {
return new Promise((resolve, reject) => {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params
}).then((response) => response.json()).then(response => {
resolve(response);
}).catch(err => {
reject(new Error(err));
});
});
}
};
判断浏览器环境
function getSystem(){
const mac = /mac/i,
linux = /linux/i,
win = /win/i;
const platform = navigator.platform.toLowerCase();
if(mac.test(platform)){
return 'MAC';
} else if(win.test(platform)){
return 'WIN';
} else if(linux.test(platform)){
return 'Linux';
}
return undefined;
}
const browser = {
versions:function(){
let ret = 'xxSys';
const u = navigator.userAgent;
const isMobile = !!u.match(/AppleWebKit.*Mobile.*/),
ios = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
android = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
if(isMobile){
if(ios) return 'IOS';
if(android) return 'Android';
} else {
ret = getSystem() || ret;
}
return ret;
}(),
};
定义数组内部对象形式
const objArrtransArr = (olddata, oldval, oldname)=>{
const newArr = [];
olddata.forEach(item => {
// 定义数组内部对象形式
let obj = {};
obj.value = item[oldval];
obj.name = item[oldname];
// 将对象数据推到数组中
newArr.push(obj);
});
return newArr;
}
解析html字符串
function (htmlobj) {
var el = document.createElement('div');
el.innerHTML = htmlobj;
var tags = el.getElementsByTagName('img');
var text = tags[0].getAttribute("src");
return text;
}
判断浏览器是否支持摄像头
function videoCheck () {
var deviceList = [];
navigator.mediaDevices
.enumerateDevices()
.then(devices => {
devices.forEach(device => {
deviceList.push(device.kind);
});
if (deviceList.indexOf("videoinput") == "-1") {
console.info("没有摄像头");
return false;
} else {
console.info("有摄像头");
}
})
.catch(function(err) {
alert(err.name + ": " + err.message);
});
}
回文算法
//忽略标点符号、大小写和空格,正着读和反着读一模一样。
function made(str) {
var str1 = str.toLowerCase(); //先将字符串全部转换为小写
var reg = /[\W\_]/g; // 删除所有非字母数字字符和下划线
var str2 = str1.replace(reg, ""); // 去掉非字母和非数字
var str3 = str2.split(""); // 字符串分隔成数组
var str4 = str3.reverse(); // 反转数组中的元素
var str5 = str4.join(""); // 反转后的数组转化为字符串
return str2 === str5;
}
持续更新…
结语
欢迎关注我的公众号前端历劫之路
回复关键词电子书,即可获取12本前端热门电子书。
回复关键词红宝书第4版,即可获取最新《JavaScript高级程序设计》(第四版)电子书。
关注公众号后,点击下方菜单即可加我微信,我拉拢了很多IT大佬,创建了一个技术交流、文章分享群,期待你的加入。
作者:Vam的金豆之路
主要领域:前端开发
我的微信:maomin9761
微信公众号:前端历劫之路