/****************************************** Array start ******************************************/
// 初始化数组
// Array(len).fill() === Array.from({length: len}) ????
const ArrayInitWithLen = len => Array(len).fill().map((v, i) => i++)
const ArrayInitWithRange = (start, end) => Array.from({ length: end - start }).map((v, i) => i + start)
const ArrayInitWithVal = (len, val) => Array(len).fill(val)
// 返回最大值元素
const ArrayMax = arr => Math.max(...arr)
// 返回最小值元素
const ArrayMin = arr => Math.min(...arr)
// 返回一个数字数组的总和
const ArraySum = arr => arr.reduce((acc, val) => acc + val, 0)
// 返回数字数组的平均值
const ArrayAverage = arr => ArraySum(arr)/arr.length
// 返回数字数组的中间值
const ArrayMiddle = arr => {
let mid = Math.floor(arr.length / 2),
nums = arr.sort((a, b) => a - b)
return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
}
/**
* [数组排序]
* @param {[type]} arr [数组]
* @param {[type]} key) [key]
* @return {[type]} [description]
*/
const ArraySortBy = (arr, key) => arr.sort((a, b) => {
if(key === undefined){
return a - b
}else if(typeof key === 'function'){
return arr.sort(key)
}else if(isNaN(a[key])){
return a[key].localeCompare(b[key])
}else{
return a[key] - b[key]
}
})
// 扁平化数组
const ArrayFlat = (arr, depth = Infinity) => arr.flat(depth)
// 数组去重
const ArrayDuplicate = arr => [...new Set(arr)]
// 将数组按照长度分段
const ArrayChunk = (arr, len) => Array.from({ length: Math.ceil(arr.length / len) }, (v, i) => arr.slice(i * len, i * len + len))
// 筛选出 falsey 值 ( false、 null、 0、 ''、 undefined 和 NaN )
const ArrayCompact = arr => arr.filter(Boolean)
// 返回唯一值
const ArrayUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
// 随机数组值的顺序
const ArrayShuffle = arr => arr.sort(() => Math.random() - 0.5);
// 计算元素出现的次数
const ArrayCountOccurrences = (arr, val) => arr.reduce((a, v) => v === val ? a + 1 : a, 0)
// 返回数组中每间隔第 n 个元素
const ArrayEveryNth = (arr, nth) => arr.filter((e, i) => i % nth === 0)
// 返回两个数组中都存在的元素
const ArraySimilarity = (arr1, arr2) => arr1.filter(v => arr2.includes(v))
// 返回第一个数组与第二个数组不同的元素
const ArrayDifference = (arr1, arr2) => { let s = new Set(arr2); return arr1.filter(x => !s.has(x)); }
// 返回两个数组之间的差集(差异的部分)
const ArraySymmetricDifference = (arr1, arr2) => {
let sA = new Set(arr1),
sB = new Set(arr2);
return [...arr1.filter(x => !sB.has(x)), ...arr2.filter(x => !sA.has(x))]
}
/******************************************* Array end *******************************************/
/******************************************* Date start ******************************************/
// 返回两个日期之间的差异 (以天为值)
const DateGetDaysBetween = (start, end) => (start - end) / (1000 * 3600 * 24)
/******************************************* Date end ********************************************/
/****************************************** Number start *****************************************/
// 返回指定范围内的随机数, floor 是否生成整数
const NumberRandomInRange = (min, max, floor) => {
let random = Math.random() * (max - min + floor)
return (floor ? Math.floor(random) : random) + min
}
// 将数字四舍五入到指定的位数
const NumberRound = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`).toFixed(decimals)
/******************************************* Number end ******************************************/
/****************************************** String start *****************************************/
// 将字符串的第一个字母大写
const StringCapitalize = ([first, ...rest], lowerRest = false) => first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''))
// 将字符串中每个单词的首字母大写
const StringCapitalizeEvery = str => str.replace(/\b[a-z]/g, char => char.toUpperCase())
// 从匹配转换字符串(将驼峰写法转换成自定义分隔符的写法)
const StringFromCamelCase = (str, separator = '_') => str.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2').toLowerCase();
// 将字符串转换为匹配
const StringToCamelCase = str => str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) => p2 ? p2.toUpperCase() : p1.toLowerCase())
// 反转字符串
const StringReverse = str => [...str].reverse().join('')
// 按字母顺序对字符串中的字符进行排序
const StringSort = str => str.split('').sort((a, b) => a.localeCompare(b)).join('')
// 将字符串截断为指定长度, 并拼接自定义字符串
const StringTruncate = (str, num, separator = '...') => str.length > num ? str.slice(0, num) + separator : str
/******************************************* String end ******************************************/
/********************************************* is start ******************************************/
const isArray = val => Array.isArray(val)
const isString = val => typeof val === 'string'
const isNumber = val => typeof val === 'number'
const isBoolean = val => typeof val === 'boolean'
const isFunction = val => typeof val === 'function'
const isSymbol = val => typeof val === 'symbol'
// 基本类型
const isStatic = type => type === null || ['string','number', 'boolean', 'undefined', 'symbol'].includes(typeof type)
// 注意: function 不是 原始类型,这里加进去是因为可以用 typeof 返回
const isUndefined = type => typeof type === 'undefined'
const isNull = type => type === null
/********************************************** is end *******************************************/
/******************************************* getType start ***************************************/
const getRef = function (obj) {
let _type = Object.prototype.toString.call(obj).slice(8, -1)
let map = {
'Array': 'array',
'Object': 'object',
'Function': 'function',
'Date': 'date',
'RegExp': 'regExp'
}
return map[_type]
}
const getType = function (obj) {
return obj === null ? 'null' : isStatic(obj) ? typeof obj : getRef(obj)
}
/********************************************* getType end ***************************************/
/******************************************* DOM start *******************************************/
// 如果页面的底部可见, 则返回true , 否则为false
const DomIsBottomVisible = () => document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight
// 如果指定的元素在视区中可见, 则返回true , 否则为false。 第二个参数是否完全可见
const DomIsElementInViewport = (el, partiallyVisible = false) => {
let { top, left, bottom, right } = el.getBoundingClientRect();
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
};
// 返回当前页的滚动位置
const DomGetScrollPosition = (el = window) => {
return {
x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft,
y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop
}
}
// 元素
const DomGetEle = el => document.querySelector(el)
const DomGetEles = el => document.querySelectorAll(el)
const DomEleToArray = el => Array.from(DomGetEles(el))
// classList
const DomGetEleClass = el => DomGetEle(el).classList
const DomEleHasClass = (el, cls) => DomGetEleClass(el).contains(cls)
const DomToggleClass = (el, cls) => DomGetEleClass(el).toggle(cls)
// 属性
const DomGetEleAttr = (el, key) => DomGetEle(el).getAttribute(key)
const DomSetEleAttr = (el, key) => DomGetEle(el).setAttribute(key)
// 位置尺寸
const DomGetEleClientRect = (el, key) => {
let rect = DomGetEle(el).getBoundingClientRect();
return !!key ? rect[k] : rect
}
// 这里这里还不清楚 offsetHeight 与 clientHeight 的区别
const DomGetEleOffset = (el, key) => {
if(!!key) throw new Error('missing required options')
return DomGetEle(el)[`offset${StringCapitalize(key)}`]
}
const DomGetEleClient = (el, key) => {
if(!!key) throw new Error('missing required options')
return DomGetEle(el)[`Client${StringCapitalize(key)}`]
}
// 平滑滚动到页面顶部
const DomScrollToTop = () => {
let c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(DomScrollToTop);
window.scrollTo(0, c - c / 8);
}
}
/******************************************** DOM end ********************************************/
/******************************************* BOM start *******************************************/
// 返回当前 URL
const BomGetCurrentURL = () => window.location.href
// 返回一个包含当前 URL 参数的对象
const BomGetURLParams = url => url.match(/([^?=&]+)(=([^&]*))/g).reduce((a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {})
/******************************************** BOM end ********************************************/
exports._is = {
string: isString,
number: isNumber,
boolean: isBoolean,
_undefined: isUndefined,
_null: isNull,
symbol: isSymbol,
function: isFunction,
array: isArray,
static: isStatic,
}
exports._type = {
getRef: getRef,
getType: getType,
}
exports._string = {
capitalizeFirst: StringCapitalize,
capitalizeEvery: StringCapitalizeEvery,
fromCamelCase: StringFromCamelCase,
toCamelCase: StringToCamelCase,
reverse: StringReverse,
sort: StringSort,
truncate: StringTruncate
}
exports._date = {
getDaysBetween: DateGetDaysBetween
}
exports._number = {
randomInRange: NumberRandomInRange,
round: NumberRound
}
exports._array = {
initWithLen: ArrayInitWithLen,
initWithRange: ArrayInitWithRange,
initWithVal: ArrayInitWithVal,
max: ArrayMax,
min: ArrayMin,
sum: ArraySum,
average: ArrayAverage,
middle: ArrayMiddle,
sortBy: ArraySortBy,
flat: ArrayFlat,
duplicate: ArrayDuplicate,
chunk: ArrayChunk,
compact: ArrayCompact,
unique: ArrayUnique,
shuffle: ArrayShuffle,
countOccurrences: ArrayCountOccurrences,
everyNth: ArrayEveryNth,
similarity: ArraySimilarity,
difference: ArrayDifference,
symmetricDifference: ArraySymmetricDifference,
}
exports._object = {
}
exports._clone = {
}
exports._dom = {
isBottomVisible: DomIsBottomVisible,
isElementInViewport: DomIsElementInViewport,
getScrollPosition: DomGetScrollPosition,
getEle: DomGetEle,
getEles: DomGetEles,
eleToArray: DomEleToArray,
getClass: DomGetEleClass,
hasClass: DomEleHasClass,
toggleClass: DomToggleClass,
getAttr: DomGetEleAttr,
setAttr: DomSetEleAttr,
getClientRect: DomGetEleClientRect,
getOffset: DomGetEleOffset,
getClient: DomGetEleClient,
scrollToTop: DomScrollToTop,
}
exports._bom = {
getCurrentURL: BomGetCurrentURL,
getURLParams: BomGetURLParams,
}