数字
在一定范围内去一个随机整数
function randomIntegerInRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
判断数字是否为奇数
function isEven(num) {
return num % 2 === 0;
}
截取小数点 (非四舍五入)
function toFixed(value, fixed) {
return ~~(Math.pow(10, fixed) * value) / Math.pow(10, fixed);
}
console.log(toFixed(1.123456789, 0)); // 1
console.log(toFixed(1.123456789, 1)); // 1.1
console.log(toFixed(1.123456789, 2)); // 1.12
console.log(toFixed(1.123456789, 3)); // 1.123
console.log(toFixed(1.123456789, 4)); // 1.1234
console.log(toFixed(1.123456789, 5)); // 1.12345
验证数字,可以包含负号和小数点
function isNumber(number) {
if(!number && number != 0) {
console.error('请输入需要验证的数字');
return;
}
let regex = /^-?\d+$|^(-?\d+)(\.\d+)?$/;
if (number.toString().match(regex)) {
return true;
} else {
return false;
}
}
验证整数,可以包含负整数
function isInteger(integer){
if(!integer && integer != 0) {
console.error('请输入需要验证的整数');
return;
}
let regex = /^-?\d+$/;
if (integer.toString().match(regex)) {
return true;
} else {
return false;
}
}
验证小数
function isDecimal(decimal) {
if(!decimal) {
console.error('请输入需要验证的小数');
return;
}
let regex = /^([-+]?[1-9]\d*\.\d+|-?0\.\d*[1-9]\d*)$/;
if (decimal.toString().match(regex)) {
return true;
} else {
return false;
}
}
布尔
随机一个布尔值
function randomBoolean() {
return Math.random() >= 0.5;
}
字符串
大写每个单词的首字母
function capitalizeEveryWord(str) {
return str.replace(/\b[a-z]/g, char => char.toUpperCase());
}
反转一个字符串
方式一
function reverseString(str){
return [...str].reverse().join('');
}
方式二
function reverseString(str) {
return str.split('').reverse().join('');
}
按字母顺序排序字符串,返回排序后的字符串
function sortCharactersInString(str) {
return str.split('').sort((a, b) => a.localeCompare(b)).join('');
}
删除字符串中连续得字符
function uniq(str) {
return str.replace(/(\w)\1+/g, '$1')
}
删除字符串两端空格
function trim(string) {
return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
}
ECMAScript5为字符串也提供了trim()方法。
var str = ' 橙某人 ';
console.log(str.trim()); // 橙某人
// 但如果你的浏览器不支持trim()方法,你可以使用上面方法通过正则表达式来实现。
寻找字符串中第一次只出现一次的字母
function firstAppear(str) {
var obj = {},
len = str.length;
for (var i = 0; i < len; i++) {
if (obj[str[i]]) {
obj[str[i]]++;
} else {
obj[str[i]] = 1;
}
}
for (var prop in obj) {
if (obj[prop] == 1) {
return prop;
}
}
}
console.log(firstAppear('aabbcddfee')); // c
console.log(firstAppear('aabbccddfee')); // f
检验字符串是否是回文
方式一
function isPalina(str) {
if (Object.prototype.toString.call(str) !== '[object String]') {
return false;
}
var len = str.length;
for (var i = 0; i < len / 2; i++) {
if (str[i] != str[len - 1 - i]) {
return false;
}
}
return true;
}
方式二
function isPalindrome(str) {
str = str.replace(/\W/g, '').toLowerCase();
return (str == str.split('').reverse().join(''));
}
获取url中得参数
function getUrlParams(url) {
var args = url.split('?');
if (args[0] === url) return ({});
var hrefarr = args[1].split('#')[0].split('&');
var obj = {};
for (var i = 0; i < hrefarr.length; i++) {
hrefarr[i] = hrefarr[i].split('=');
if(hrefarr[i][0])
obj[hrefarr[i][0]] = hrefarr[i][1];
}
return obj;
}
提取img标签得src
function getImgEleSrc(imgEle = '') {
return imgEle.match(/src=[\'\"]?([^\'\"]*)[\'\"]?/i)[1];
}
console.log(getImgEleSrc('<img src="https://juejin.cn/" alt="" />')); // https://juejin.cn/
过滤特殊字符
/**
* @param str: 需要过滤的字符
* @param rule: 自定义特殊字符
* @param append: 在默认特殊字符上追加过滤的特殊字符
* @returns string: 过滤后的字符
*/
function filterStr(str, rule, append) {
if(!rule) rule = "[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]";
if(append) rule = rule.slice(0, 1) + append + rule.slice(1);
let pattern = new RegExp(rule);
let retrunStr = '';
for (let i = 0;i < str.length;i++){
retrunStr = retrunStr + str.substr(i, 1).replace(pattern, '');
}
return retrunStr;
}
截取指定长度的字符串
/**
* @description 截断字符
* @type {{func: truncate.func}}
*/
function truncate(value, length) {
if(!value) return value;
if(value.length <= length) return value;
return value.slice(0, length) + '...';
}
数组
判断是否是一个数组
function isArray(arr) {
return arr instanceof Array;
}
// or
function isArray(arr) {
return Array.isArray(arr);
}
当检测Array实例时,Array.isArray优于instanceof,因为Array.isArray能检测iframes。
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var iArray = window.frames[window.frames.length-1].Array;
var arr = new iArray(1,2,3); // [1,2,3]
console.log(Array.isArray(arr)); // true
console.log(arr instanceof Array); // false
数组求总和
/**
* @param arr: 其中值只能是整数, 小数, 数字字符串
*/
function arraySum(arr) {
return arr.reduce((acc, val) => parseFloat(acc) + parseFloat(val), 0);
}
随机打乱数组得排序,返回打乱后的数组
function randomizeOrder(arr) {
return arr.sort((a, b) => Math.random() >= 0.5 ? -1 : 1)
}
数组去重
方式一
function arrayDuplicateRemoval(arr) {
return [...new Set(arr)];
}
方式二
function arrayDuplicateRemoval(arr) {
var obj = {};
var result = [];
for (var i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) {
obj[arr[i]] = true;
result.push(arr[i])
}
}
return result;
}
方式三
function arrayDuplicateRemoval(arr) {
var obj = {};
return arr.filter(ele => {
if (!obj[ele]) {
obj[ele] = true;
return true;
}
})
}
方式四
function arrayDuplicateRemoval(arr) {
var result = [];
arr.forEach(ele => {
if (result.indexOf(ele) == -1) {
result.push(ele)
}
})
return result;
}
对象
判断是否是一个对象
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
清空对象的值
/**
* @ignoreKey Array or String: 忽略一些key不清空
*/
function clearEmptyObject(object, ignoreKey) {
if(typeof object !== 'object') return;
for(let key in object) {
if(Object.prototype.toString.call(object[key]) === '[object Object]') {
clearEmptyObject(object[key]);
}
else {
if(ignoreKey && (
(typeof ignoreKey === 'string' && ignoreKey === key) ||
(ignoreKey instanceof Array && ignoreKey.includes(key))
)) return;
if(Array.isArray(object[key])) {
object[key] = [];
}else {
if(typeof object[key] === 'boolean') {
object[key] = false;
}else {
object[key] = '';
}
}
}
}
}
日期
判断是否是合法日期
/**
* @method 判断是否为合法日期
* @param date 为Date转化后的值
*/
function isValidDate(date) {
return date instanceof Date && !isNaN(date.getTime())
}
判断某个月有多少天
/**
* @method 获取某个月有多少天数
* @param year 年
* @param month 月(如:2)
*/
function getDaysInMonth(year, month) {
return new Date(year, month, 0).getDate()
}
判断两个日期之间的天数插值
/**
* @method 判断两个日期之间的天数差值
* @param {*} endDate 结束天数 日期格式为字符串2018-01-01
* @param {*} startDate 开始日期 日期格式为字符串2018-01-01
*/
function DateDifference (endDate, startDate) {
return parseInt((Math.abs(new Date(endDate) - new Date(startDate)) / 1000 / 60 / 60 / 24) + 1)
}
各种日期转换格式
function dateChangeFormat(date = new Date(), format = 'yyyy-MM-dd', char = '-') {
if(!(date instanceof Date)) {
date = new Date(date);
}
let YYYY = date.getFullYear();
let MM = date.getMonth() + 1 > 9 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1);
let DD = date.getDate() > 9 ? date.getDate() : '0' + date.getDate();
let hh = date.getHours() > 9 ? date.getHours() : '0' + date.getHours();
let mm = date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes();
let ss = date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds();
switch (format) {
case 'yyyy-MM-dd': return `${YYYY}${char}${MM}${char}${DD}`;break;
case 'yyyy-MM-dd hh:mm:ss': return `${YYYY}${char}${MM}${char}${DD} ${hh}:${mm}:${ss}`; break;
case 'text': return `${YYYY}年${MM}月${DD}日`;break;
case 'text hh:mm:ss': return `${YYYY}年${MM}月${DD}日 ${hh}:${mm}:${ss}`;break;
case 'empty': return `${YYYY}${MM}${DD}${hh}${mm}${ss}`;break;
}
}
更多其他格式,直接添加一个case。
检查日期是否是工作日
function isWeekday(date) {
return date.getDay() % 6 !== 0;
}
判断一个时间是否位于两时间之间
/**
* @method 判断一个时间是否位于两时间之间
* @param sDate1,sDate2为日期,如:2019-01-01
*/
function dateBetweenJudget(startDate, endDate, date) {
let oStartDate = new Date(startDate)
let oEndDate = new Date(endDate)
let oDate = new Date(date)
if ((oEndDate.getTime() >= oDate.getTime()) && (oStartDate.getTime() <= oDate.getTime())) {
return true
}
return false
}
比较两个时间大小
/**
* @param date1: 日期类型 or YYYY-MM-DD ; 基准
* @param date2: 日期类型 or YYYY-MM-DD ; 默认和当前日期比较
* @param compareTime: 是否比较时间
* @returns boolean -1 0 1
*/
function compareDate(date1, date2 = new Date(), compareTime = false){
let flag = null;
if(!date1) {
console.warn('请输入比较的日期');
return;
}
if(!(date1 instanceof Date)) {
date1 = new Date(date1.replace(/-/g,"\/"));
}
if(!(date2 instanceof Date)) {
date2 = new Date(date2.replace(/-/g,"\/"));
}
// 不比较时间,只比较日期
if(!compareTime) {
date1 = new Date(date1.getFullYear() + '/' + (date1.getMonth()+1) + '/' + date1.getDate());
date2 = new Date(date2.getFullYear() + '/' + (date2.getMonth()+1) + '/' + date2.getDate());
}
if(date1.getTime() < date2.getTime()){
flag = -1;
}else if(date1.getTime() == date2.getTime()) {
flag = 0;
}else {
flag = 1;
}
return flag;
}
获取某个月份的全部天数
function getMonthAllDays(year, month) {
let monthData = [];
// 初始默认值
if (!year || !month) {
year = new Date().getFullYear();
month = new Date().getMonth() + 1;
}
// 获取本月第一天和这天是星期几
let curMonthFirstDay = new Date(year, month - 1, 1);
let curMonthFirstDayWeek = curMonthFirstDay.getDay() === 0 ? 7 : curMonthFirstDay.getDay();
year = curMonthFirstDay.getFullYear();
month = curMonthFirstDay.getMonth() + 1;
// 获取本月最后一天和这天是几号
let curMonthLastDay = new Date(year, month, 0);
let curMonthLastDayNum = curMonthLastDay.getDate();
// 获取上个月最后一天和这天是几号
let prevMonthLastDay = new Date(year, month - 1, 0); // month - 1:为原来的月份,0:可以变成一个月最后一天
let prevMonthLastDayNum = prevMonthLastDay.getDate();
// 计算补多少天为上个月的
let prevMonthDayCount = curMonthFirstDayWeek - 1; // 设计本月1号为周四,则4-1 = 3,还要补三天
for (let i = 0; i < 7 * 6; i++){
let date = i - prevMonthDayCount;
let showDay = date;
let showMonth = month;
let showYear = year;
// 天数越界处理
if (date <= 0) {
// 上一个月
showDay = prevMonthLastDayNum + date;
showMonth = month - 1;
}
else if (date > curMonthLastDayNum) {
// 下个月
showDay = showDay - curMonthLastDayNum;
showMonth = month + 1;
}
// 月数越界处理
if (showMonth <= 0) showMonth = 12;
if (showMonth > 12) showMonth = 1;
// 年数越界处理
if(month === 12 && showMonth === 1) showYear = year + 1;
if(month === 1 && showMonth === 12) showYear = year - 1;
monthData.push({
showYear,
showMonth,
showDay,
date,
isCurrentDay: compareDate(showYear + '/' + showMonth + '/' + showDay), // 这里借助了上面compareDate函数比较两个日期
isSaturday: new Date(showYear + '/' + showMonth + '/' + showDay).getDay() === 6 ? 1 : 0,
isSunday: new Date(showYear + '/' + showMonth + '/' + showDay).getDay() === 0 ? 1 : 0
})
}
return {
year,
month,
days: monthData
}
}
Dom
判断是否存在class
/**
* @param el: Dom元素
* @param cls: 多个空格隔开
*/
function hasClass(el, cls) {
if (!el || !cls) return false;
if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');
if (el.classList) {
return el.classList.contains(cls);
} else {
return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
}
添加class
/**
* @param el: Dom元素
* @param cls: 多个空格隔开
*/
function addClass(el, cls) {
if (!el) return;
var curClass = el.className;
var classes = (cls || '').split(' ');
for(var i = 0, j = classes.length; i < j; i++) {
var clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.add(clsName);
} else if (hasClass(el, clsName)) { // 这里调用了上面的hasClass方法
curClass += ' ' + clsName;
}
}
if (!el.classList) {
el.className = curClass;
}
}
删除class
/**
* @param el: Dom元素
* @param cls: 多个空格隔开
*/
function removeClass(el, cls) {
if (!el || !cls) return;
var classes = cls.split(' ');
var curClass = ' ' + el.className + ' ';
for (var i = 0, j = classes.length; i < j; i++) {
var clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.remove(clsName);
} else if (hasClass(el, clsName)) { // 这里调用了上面的hasClass方法
curClass = curClass.replace(' ' + clsName + ' ', ' ');
}
}
if (!el.classList) {
el.className = (curClass || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
}
}
浏览器
判断浏览器当前Tab页是否可见
function isBrowserTabInView() {
return document.hidden;
}
判断一个元素当前是否是聚集焦点状态
document.activeElement API所有浏览器都支持
function elementIsInFocus(el) {
return el === document.activeElement;
}
判断浏览器是否支持触摸事件
支持返回true,不支持返回undefined
function touchSupported() {
return ('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch);
}
让页面滚动到页面顶部
window.scrollTo()方法会取一个 x 和 y 坐标来进行滚动,IE不支持 scrollTo()方法。
function goToPageTop() {
return window.scrollTo(0, 0);
}
判断元素有没有子元素
function hasChildren(e) {
var children = e.childNodes;
var len = children.length;
for(var i = 0; i < len; i++) {
if (children[i].nodeType === 1) {
return true;
}
}
return false;
}
获得滚动条的滚动距离
function getScrollOffset() {
if (window.pageXOffset) {
return {
x: window.pageXOffset,
y: window.pageYOffset
}
} else {
return {
x: document.body.scrollLeft + document.documentElement.scrollLeft,
y: document.body.scrollTop + document.documentElement.scrollTop
}
}
}
获得视口的尺寸
function 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
}
}
}
}
取消冒泡的兼容代码
function stopBubble(e) {
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
}
其他
判断值为空
function isEmpty(val) {
if (val === 0) return false;
// null or undefined
if (val == null) return true;
if (typeof val === 'boolean') return false;
if (typeof val === 'number') return !val;
if (val instanceof Error) return val.message === '';
switch (Object.prototype.toString.call(val)) {
// String or Array
case '[object String]':
case '[object Array]':
return !val.length;
// Map or Set or File
case '[object File]':
case '[object Map]':
case '[object Set]': {
return !val.size;
}
// Plain Object
case '[object Object]': {
return !Object.keys(val).length;
}
}
return false;
}
输入一个值,返回它的数据类型
function type(value) {
return Object.prototype.toString.call(value);
}
var typeMaps = [1, '1', true, null, undefined, {}, [], () => {}, new Date()];
typeMaps.forEach(value => console.log(type(value)));
/* 结果
[object Number]
[object String]
[object Boolean]
[object Null]
[object Undefined]
[object Object]
[object Array]
[object Function]
[object Date]
*/
RGB转十六进制
function rgbToHex(r, g, b){
return '#' + ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
}
console.log(rgbToHex(255, 255, 255)); // #ffffff
console.log(rgbToHex(0, 0, 0)); // #000000
深拷贝
方式一
JSON.parse()、JSON.stringify()很简单粗暴,但是元素只能是对象或者数组,对于函数、日期等其他类型是有问题的。
function deepCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
let arr = [() => {}, { b: () => {} }, new Date()];
let newArr = JSON.parse(JSON.stringify(arr));
console.log(newArr);
let obj = {a: () => {}, b: new Date()};
let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj);
函数会整个不见,日期类型会变成字符串。
方式二
递归的方式,对于其他类型的元素需要添加特定的判断。
function deepCopy(obj) {
if (typeof obj !== 'object') return;
let result = obj instanceof Array ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = typeof obj[key] === 'object' && !(obj[key] instanceof Date) ? deepCopy(obj[key]) : obj[key];
}
}
return result;
}
获取星级
function getLevel(rate) {
return "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);
}
防抖函数
function debounce(fn, delay = 500) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
节流函数
function throttle(fn, gapTime) {
let _lastTime = null;
return function () {
let _nowTime = + new Date()
if (_nowTime - _lastTime > gapTime || !_lastTime) {
fn();
_lastTime = _nowTime
}
}
}
固定电话或手机号码
function isTelePhoneNumber(phone) {
if(!phone) {
console.error('请输入需要验证的固定电话或手机号码');
return;
}
let reg = /^[1][3,4,5,6,7,8][0-9]{9}$|^0\d{2,3}-?\d{7,8}$/;
if (phone.toString().match(reg)) {
return true;
} else {
return false;
}
}
验证手机号码
function isPhoneNumber(phone) {
if(!phone) {
console.error('请输入需要验证的手机号码');
return;
}
let reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
if (phone.toString().match(reg)) {
return true;
} else {
return false;
}
}
验证税号,15或者17或者18或者20位字母、数字组成
function isCheckTax(tax) {
if(!tax) {
console.error('请输入需要验证的税号');
return;
}
let reg = /^[A-Z0-9]{15}$|^[A-Z0-9]{17}$|^[A-Z0-9]{18}$|^[A-Z0-9]{20}$/;
if (tax.toString().match(reg)) {
return true;
} else {
return false;
}
}
验证的身份证号,可验证一代或者二代身份证
function isIdCard(input) {
if(!input) {
console.error('请输入需要验证的身份证号');
return;
}
input = input.toUpperCase();
// 验证身份证号码格式,一代身份证号码为15位的数字;二代身份证号码为18位的数字或17位的数字加字母X
if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/i.test(input))) {
return false;
}
// 验证省份
let arrCity = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江 ',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外'
};
if(arrCity[parseInt(input.substr(0, 2))] == null) {
return false;
}
// 验证出生日期
let regBirth, birthSplit, birth;
let len = input.length;
if(len == 15) {
regBirth = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/);
birthSplit = input.match(regBirth);
birth = new Date('19' + birthSplit[2] + '/' + birthSplit[3] + '/' + birthSplit[4]);
if (!(birth.getYear() == Number(birthSplit[2]) && (birth.getMonth() + 1) == Number(birthSplit[3]) && birth.getDate() == Number(birthSplit[4]))) {
return false;
}
return true;
}else if(len == 18) {
regBirth = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/i);
birthSplit = input.match(regBirth);
birth = new Date(birthSplit[2] + '/' + birthSplit[3] + '/' + birthSplit[4]);
if(!(birth.getFullYear() == Number(birthSplit[2]) && (birth.getMonth() + 1) == Number(birthSplit[3]) && birth.getDate() == Number(birthSplit[4]))) {
return false;
}
// 验证校验码
let valnum;
let arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
let arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
let nTemp = 0, i;
for (i = 0; i < 17; i++) {
nTemp += input.substr(i, 1) * arrInt[i];
}
valnum = arrCh[nTemp % 11];
if (valnum != input.substr(17, 1)) {
return false;
}
return true;
}
return false;
}
邮箱校验
function isEmail(email) {
return /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/.test(email);
}