viperjs v1.0.2
viperjs
常用js片段组成的工具库,代码是es6编写,可以拿出单条片段进行babel再使用。
获取
# npm
npm install viperjs目录
ARRAY
arrayConcatdifferenceincludesintersectionremovesamplesamplesizechunkcompactcountoccurrencesdeepFlattenflattenforeachrightdistinctvaluesofarraydroprighteverynthfilternonuniqueindexofallinitialinitializearraywithrangeinitializearraywithvaluesissortedjoinlastlongestitemmaxnminnnthelementpartitionpullpullatindexpullatvaluereducedfiltershufflesimilaritysymmetricdifferencetailtaketakerightunionwithoutzipzipobjectaverage
BROWSER
FUNCTION
Math
OBJECT
OBJECT
digitizeanagramsbyteSizecapitalizecapitalizeeverywordescapehtmlfromcamelcasemaskpalindromereversestringsortstringtocamelCasetruncatestringunescapehtml
Type
UTILITY
coalescecoalescefactoryextendhexgeturlparamshextorgbrandomhexcodergbtohextimetakenuuidgeneratorbrowservalidemail
ARRAY
ArrayConcat
数组拼接
viper.ArrayConcat = (arr, ...args) => [].concat(arr, ...args);viper.ArrayConcat([1], [1, 2, 3, [4]]) // [1, 2, 3, [4]]difference
数组比较 过滤出数组 a中数组b不包含的值
viper.difference = (a, b) => {
const s = new Set(b)
return a.filter(x => !s.has(x))
}viper.difference([1,2,3], [1,2])
// [3]includes
数组|字符串包含
viper.includes = (collection, val, formIdex=0) => collection.slice(formIdex).indexOf(val) != -1viper.includes("30-seconds-of-code", "code") // true
viper.includes([1, 2, 3, 4], [1, 2], 1) // falseintersection
数组交集 返回两数组中同时包含的值
viper.intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x))}viper.intersection([1,2,3], [4,3,2]) // [2,3] remove
根据函数移除数组中的元素并返回移除元素
viper.remove = (arr, fn) => Array.isArray(arr) ? arr.filter(fn).reduce((acc, val) => {
arr.splice(arr.indexOf(val), 1);
return acc.concat(val)
}, []) : []viper.remove([1, 2, 3, 4], n => n % 2 == 0) // [2, 4]sample
随机获取数组或字符串中一个元素
viper.sample = arr => arr[Math.floor(Math.random() * arr.length)]viper.sample([1,2,3]) // 2 sampleSize
从数组中获取n个随机元素,最大为数组的大小
viper.sampleSize = ([...arr], n = 1) => {
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
[arr[m], arr[i]] = [arr[i], arr[m]];
}
return arr.slice(0, n);
};viper.sampleSize([1, 2, 3], 2); // [1,3]
viper.sampleSize([1, 2, 3], 4); // [1,3,2]chunk
chunk分割成指定大小的数组, 如果不能整分,剩余的会组成一个新的数组
viper.chunk = (arr, size) => Array.from({length: Math.ceil(arr.length / size)}, (v, i) =>{
return arr.slice(i * size, i * size + size)
})viper.chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]compact
删除数组中错误的值 false, null, 0, “”, undefined, and NaN
viper.compact = arr => arr.filter(Boolean)viper.compact([1, false, NaN]) // [1]countOccurrences
统计数组中某个值出现的次数
viper.countOccurrences = (arr, val) => arr.reduce((a, v)=>(v === val ? a + 1 : a + 0), 0);viper.countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3deepFlatten
深度平铺数组 转换为一维数组
viper.deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)))viper.deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]flatten
创建指定唯度的数组 默认为1
viper.flatten = (arr, depth =1) => depth != 1
? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flatten(v, depth - 1) : v), [])
: arr.reduce((a, v) => a.concat(v), [])viper.flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
viper.flatten([1, [2], 3, 4]); // [1, 2, 3, 4]forEachRight
从数组右边开始对每个元素执行指定函数
viper.forEachRight = (arr, callback) => arr.slice(0).reverse().forEach(callback)viper.forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'distinctValuesOfArray
数组去重
viper.distinctValuesOfArray = arr => [...new Set(arr)]viper.distinctValuesOfArray([1, 2, 2, 3, 4, 4, 5]); // [1,2,3,4,5]sampleSize
从右删除指定位置n的元素, n默认为1
viper.dropRight = (arr, n = 1) => arr.slice(0, -n)
};viper.dropRight([1, 2, 3]); // [1,2]
viper.dropRight([1, 2, 3], 2); // [1]
viper.dropRight([1, 2, 3], 42); // []everyNth
返回数组中的每个第n个元素
viper.everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);viper.everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ]ArrayConcat
返回数组中唯一值
viper.filterNonUnique = arr => arr.filter( i => arr.indexOf(i) === arr.lastIndexOf(i))viper.filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1,3,5]11111111
indexOfAll
返回数组中val出现的所有索引
viper.indexOfAll = (arr, val) => {
const indices = []
arr.forEach((el, i) => el === val && indices.push(i))
return indices
}viper.indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
viper.indexOfAll([1, 2, 3], 4); // []initial
返回除最后一个数组外的所有元素
viper.initial = (arr) => arr.slice(0, -1)initial([1, 2, 3]); // [1,2]initializeArrayWithRange
初始化一个包含指定范围中的数字的数组
viper.initializeArrayWithRange = (end, start = 0, step = 1) => Array.from({length : Math.ceil((end + 1 -start) / step)}).map((v, i)=> i * step + start)viper.initializeArrayWithRange(7, 3); // [3,4,5,6,7]
viper.initializeArrayWithRange(9, 0, 2); // [0,2,4,6,8]initializeArrayWithValues
初始化指定长度并填充初始值
viper.initializeArrayWithValues = (n, val = 0) => Array(n).fill(val)viper.initializeArrayWithValues(5, 2); // [2,2,2,2,2]isSorted
是否排序 正序返回1 降序返回-1 未排序返回0
viper.isSorted = arr => {
const direction = arr[0] > arr[1] ? -1 : 1;
for(let [i, val] of arr.entries()){
if(i === arr.length - 1){
return direction
} else if((val - arr[i + 1]) * direction > 0){
return 0
}
}
}viper.isSorted([0, 1, 2, 2]); // 1
viper.isSorted([4, 3, 2]); // -1
viper.isSorted([4, 3, 5]); // 0join
使用分隔符和结束符拼接所有数组中的元素并返回拼接好的字符串
viper.join = (arr, separator = ',', end = separator) => arr.reduce((acc, val, i) => i == arr.length - 2 ? acc + val + end : i == arr.length - 1 ? acc + val : acc + val + separator, '')
};viper.join(['pen', 'pineapple', 'apple', 'pen'], ',', '&'); // "pen,pineapple,apple&pen"
viper.join(['pen', 'pineapple', 'apple', 'pen'], ','); // "pen,pineapple,apple,pen"
viper.join(['pen', 'pineapple', 'apple', 'pen']); // "pen,pineapple,apple,pen"last
返回最后一个元素
viper.last = arr => arr[arr.length - 1];viper.last([1, 2, 3]); // 3longestItem
返回多个可迭代对象中长度最长的一个
viper.longestItem = (...vals) => [...vals].sort((a, b) => b.length - a.length)[0]viper.longestItem(...['a', 'ab', 'abc'], 'abcd'); // 'abcd'
viper.longestItem([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]); // [1, 2, 3, 4, 5]
viper.longestItem([1, 2, 3], 'foobar'); // 'foobar'maxN
从提供的数组中返回n个最大元素 如果n大于或等于提供的数组长度,则返回原始数组(按降序排列)
viper.maxN = (arr, n = 1) => [...arr].sort((a,b) => b - a).slice(0, n)viper.maxN([1, 2, 3]); // [3]
viper.maxN([1, 2, 3], 2); // [3,2]minN
从提供的数组中返回n个最小元素。如果n大于或等于提供的数组长度,则返回原始数组(按升序排序)
viper.minN = (arr, n =1) => [...arr].sort((a, b) => a - b).slice(0, n)viper.minN([1, 2, 3]); // [1]
viper.minN([1, 2, 3], 2); // [1,2]nthElement
返回数组的第n个元素
viper.nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n , n + 1) : arr.slice(n)[0])viper.nthElement(['a', 'b', 'c'], 1); // 'b'
viper.nthElement(['a', 'b', 'b'], -3); // 'a'partition
根据所提供的函数对每个元素的真实性将这些元素分成两个数组
viper.partition = (arr, fn) =>{
return arr.reduce(
(acc, val, i, arr) => {
acc[fn(val, i, arr) ? 0 : 1].push(val)
return acc
},
[[], []]
)
}const users = [{ user: 'barney', age: 36, active: false }, { user: 'fred', age: 40, active: true }];
viper.partition(users, o => o.active); // [[{ 'user': 'fred', 'age': 40, 'active': true }],[{ 'user': 'barney', 'age': 36, 'active': false }]]pull
返回的过滤指定的值后的数组
viper.pull = (arr, ...args) => {
let argState = Array.isArray(args[0]) ? args[0] : args;
let pulled = arr.filter((v, i) => !argState.includes(v));
arr.length = 0;
pulled.forEach(v => arr.push(v))
}let myArray = ['a', 'b', 'c', 'a', 'b', 'c'];
viper.pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ]pullAtIndex
返回的过滤指定的索引后的数组, 返回过滤的值
viper.pullAtIndex = (arr, pullArr) => {
let removed = [];
let pulled = arr.map((v, i) => pullArr.includes(i) ? removed.push(v) : v).filter((v, i)=> !pullArr.includes(i))
arr.length = 0;
pulled.forEach(v => arr.push(v))
return removed
}
};let myArray = ['a', 'b', 'c', 'd'];
let pulled = viper.pullAtIndex(myArray, [1, 3]); // myArray = [ 'a', 'c' ] , pulled = [ 'b', 'd' ]pullAtValue
改变原始数组以过滤出指定的值,返回删除的元素
viper.pullAtValue = (arr, pullArr) => {
let removed = [],
pushToRemove = arr.forEach((v, i)=> (pullArr.includes(v) ? removed.push(v) : v)),
mutateTo = arr.filter((v,i) => !pullArr.includes(v));
arr.length = 0
mutateTo.forEach(v => arr.push(v))
return removed
}let myArray = ['a', 'b', 'c', 'd'];
let pulled = viper.pullAtValue(myArray, ['b', 'd']); // myArray = [ 'a', 'c' ] , pulled = [ 'b', 'd' ]reducedFilter
根据条件过滤一个对象数组,同时过滤未指定的键
viper.reducedFilter = (data, keys, fn) => data.filter(fn).map(el => keys.reduce((acc, key) => {
acc[key] = el[key]
return acc
}, {}))const data = [
{
id: 1,
name: 'john',
age: 24
},
{
id: 2,
name: 'mike',
age: 50
}
];
viper.reducedFilter(data, ['id', 'name'], item => item.age > 24); // [{ id: 2, name: 'mike'}]shuffle
洗牌数组
viper.shuffle = ([...arr]) => {
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
[arr[m], arr[i]] = [arr[i], arr[m]];
}
return arr
}const foo = [1, 2, 3];
viper.shuffle(foo); // [2,3,1], foo = [1,2,3]similarity
获取数组交集
viper.similarity = (arr, values) => arr.filter(v => values.includes(v))
};viper.similarity([1, 2, 3], [1, 2, 4]); // [1,2]symmetricDifference
返回两个数组之间的不同值
viper.symmetricDifference = (a, b) => {
const sA = new Set(a),
sB = new Set(b);
return [...a.filterx(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]
}viper.symmetricDifference([1, 2, 3], [1, 2, 4]); // [3,4]tail
返回数组中除第一个元素外的所有元素
viper.tail = arr => (arr.length > 1 ? arr.slice(1) : arr)viper.tail([1, 2, 3]); // [2,3]
viper.tail([1]); // [1]take
返回从头开始删除n个元素的数组
viper.take = (arr, n = 1) => arr.slice(0 ,n)viper.take([1, 2, 3], 5); // [1, 2, 3]
viper.take([1, 2, 3], 0); // []takeRight
返回从最后删除n个元素的数组
viper.takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length)viper.takeRight([1, 2, 3], 2); // [ 2, 3 ]
viper.takeRight([1, 2, 3]); // [3]union
返回数组合集
viper.union = (a ,b) => Array.from(new Set([...a, ...b]))viper.union([1, 2, 3], [4, 3, 2]); // [1,2,3,4]without
创建一个排除所有给定值的数组
viper.without = (arr, ...args) => arr.filter(v => args.indexOf(v) === -1)viper.without([2, 1, 2, 3], 1, 2); // [3]zip
根据原始数组中的位置进行分组创建新的数组 如果参数数组的长度不一致,那么在未找到值的地方使用undefined
viper.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])
})
}viper.zip(['a', 'b'], [1, 2], [true, false]); // [['a', 1, true], ['b', 2, false]]
viper.zip(['a'], [1, 2], [true, false]); // [['a', 1, true], [undefined, 2, false]]zipObject
给定一组有效的属性标识符和一个值数组,返回一个将属性关联到值的对象,未找到值的地方使用undefined
viper.zipObject = (props, values) => props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {})
};viper.zipObject(['a', 'b', 'c'], [1, 2]); // {a: 1, b: 2, c: undefined}
viper.zipObject(['a', 'b'], [1, 2, 3]); // {a: 1, b: 2}average
求数字数组的平均数
viper.average = arr => arr.reduce((acc, val) => acc + val, 0) / arr.lengthviper.average([1,2,3]) // 2BROWSER
copyToClipboard
复制字符串到剪贴板
viper.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)
}
}viper.copyToClipboard('111') // 111复制到了剪贴板getScrollPosition
返回当前页面的滚动位置
viper.getScrollPosition = (el = window) =>({
x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
})viper.getScrollPosition() // {x: 3, y: 6023}getStyle
返回指定元素的CSS规则的值
viper.getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]viper.getStyle(document.querySelector('p'), 'font-sise') // 16pxhasClass
元素是否包含类
viper.hasClass = (el, className) => el.classList.contains(className)}viper.hasClass(document.querySelector('p.box'), 'box') // turehide
隐藏指定所有元素
viper.hide = (...el) => [...el].forEach( e => (e.style.display = 'node'))sviper.hide(document.querySelectorAll('img')) // 页面中的所以img被隐藏scrollToTop
平滑返回顶部
viper.scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop
if(c > 0){
window.requestAnimationFrame(scrollToTop)
window.scrollTo(0, c - c / 8)
}
}viper.scrollToTop() // 页面返回顶部steStyle
设置元素的css样式
viper.steStyle = (el, ruleNmae, val) =>{ el.style[ruleNmae] = val }viper.steStyle(document.querySelector('p'), 'font-size', '18px') // 第一个p元素字体大小为18像素show
显示所有指定的元素
viper.show = (...el) => [...el].forEach(e.style.display = '')viper.show(document.querySelectorAll('img')) // 显示所有img标签toggleClass
切换元素类名
viper.toggleClass = (el, className) => el.classList.toggleClass(className)viper.toggleClass(document.querySelector('div.box'), 'box') // 切换box类名FUNCTION
once
确保函数只调用一次
viper.once = fn => {
let called = false;
return function(...args){
if(called) return
called = true
return fn.call(this, args)
}
}document.body.addEventListener('click', once(()=>{console.log(111)})) // 函数只会调用一次debounce
防抖
viper.debounce = (func, wait, immediate) => {
var timeout, result;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}var count = 1;
var container = document.body;
function getUserAction() {
console.log(count)
};
container.onmousemove = viper.debounce(getUserAction, 1000);MATH
factorial
阶乘
viper.factorial = n => n <= 1 ? 1 : n * factorial(n - 1)viper.factorial(6) // 720gcd
最大公约数
viper.gcd = (x, y) => !y ? x : gcd(y, x % y);viper.gcd(8, 36) // 4
viper.gcd(...[8, 36, 12]) // 4inRange
是否在指定范围内
viper.inRange = (n, start, end = null) => {
if(end && start > end) end = [start, (start = end)][0]
return end == null ? n >= 0 && n < start : n >= start && n < end
}viper.inRange(3, 4, 5) // false
viper.inRange(3, 4) // trueisDivisible
数值2能否否能整除数值1
viper.isDivisible = (first, second) => second % first === 0viper.isDivisible(3, 9) // truerandomIntegerInRange
随机获取指定范围内的整数
viper.randomIntegerInRange = (min, max) => Math.floor(Math.random() * ( max - min + 1)) + minviper.randomIntegerInRange(2, 5) // 3randomNumberInRange
随机获取指定范围内的小数
viper.randomNumberInRange = (min, max) => Math.random() * (max - min) + minviper.randomNumberInRange(2, 10); // 6.0211363285087005round
返回指定位数的小数,省略第二个参数 四舍五入为整数
viper.round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`)viper.round(4.22) // 4
viper.round(1.005, 2); // 1.01OBJECT
pick
从对象中挑选与给定键对应的键值对
viper.pick = (obj, arr) => arr.reduce((acc, curr)=> (curr in obj && (acc[curr] = obj[curr]), acc), {})viper.pick({ a: 1, b: '2', c: 3 }, ['a', 'c']); // { 'a': 1, 'c': 3 }cleanObj
删除指定属性外的其他属性
viper.cleanObj = (obj, keysToKeep = [], childIndicator) => {
Object.keys(obj).forEach(key => {
if(key === childIndicator) {
cleanObj(obj[key], keysToKeep, childIndicator)
} else if(!keysToKeep.includes(key)){
delete obj[key]
}
})
return obj
}const testObj = { a: 1, b: 2, children: { a: 1, b: 2 } };
viper.cleanObj(testObj, ['a'], 'children'); // { a: 1, children : { a: 1}}invertKeyValues
反转key和value
viper.invertKeyValues = obj => Object.keys(obj).reduce((acc, key)=> {
acc[obj[key]] = key
return acc
},{})viper.invertKeyValues({ name: 'John', age: 20 }); // { 20: 'age', John: 'name' }lowercaseKeys
小写所有key
viper.lowercaseKeys = obj => Object.keys(obj).reduce((acc, key)=> {
acc[key.toLowerCase()] = obj[key]
return acc
},{})const myObj = { Name: 'Adam', sUrnAME: 'Smith' };
const myObjLower = viper.lowercaseKeys(myObj); // {name: 'Adam', surname: 'Smith'};merge
合并两个或者多个对象
viper.merge = (...objs) => [...objs].reduce(
(acc, obj) => Object.keys(obj).reduce(
(a, k) => {
acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k];
return acc
},{}),
{}
)const object = {
a: [{ x: 2 }, { y: 4 }],
b: 1
};
const other = {
a: { z: 3 },
b: [2, 3],
c: 'foo'
};
viper.merge(object, other); // { a: [ { x: 2 }, { y: 4 }, { z: 3 } ], b: [ 1, 2, 3 ], c: 'foo' }size
获取对象、数组、字符串的大小
viper.size = val => Array.isArray(val) ? val.length : val && typeof val === 'object' ? val.size || val.length || Object.keys(val).length : typeof val === 'string' ? new Blob([val]).size : 0viper.size([1, 2, 3, 4, 5]); // 5
viper.size('size'); // 4
viper.size({ one: 1, two: 2, three: 3 }); // 3STRING
digitize
将数值字符串转换成数组
viper.digitize = n => [...`${n}`].map(i => parseInt(i))viper.digitize(123); // [1, 2, 3]anagrams
生成一个字符串所有的排列组合
viper.anagrams = str => {
if(str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : str
return str.split('').reduce((acc, letter, i) => acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), [])
}viper.anagrams('abc'); // ['abc','acb','bac','bca','cab','cba']byteSize
返回字节大小
viper.byteSize = str => new Blob([val]).sizeviper.byteSize('😀'); // 4
viper.byteSize('Hello World'); // 11Capitalize
首字母大写
viper.Capitalize = ([first, ...rest], lowerRest = false) => first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''))viper.Capitalize('fooBar'); // 'FooBar'
viper.Capitalize('fooBar', true); // 'Foobar'capitalizeEveryWord
大写单词的每个首字母
viper.capitalizeEveryWord = str => str.replace(/\d[a-z]/g, char => char.toUpperCase())viper.capitalizeEveryWord('hello world!'); // 'Hello World!'decapitalize
首字母小写
viper.decapitalize = ([first, ...rest], upperRest = false) => first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join(''));viper.decapitalize('FooBar'); // 'fooBar'
viper.decapitalize('FooBar', true); // 'fOOBAR'escapeHTML
转义HTML
viper.escapeHTML = str => str.replace(
/[&<>'"]/g,
tag => ({
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
})([tag] || tag)
)viper.escapeHTML('<a href="#">Me & you</a>'); // '<a href="#">Me & you</a>'fromCamelCase
将驼峰字符改成字符串
viper.fromCamelCase = (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()viper.fromCamelCase('someDatabaseFieldName', ' '); // 'some database field name'
viper.fromCamelCase('someLabelThatNeedsToBeCamelized', '-'); // 'some-label-that-needs-to-be-camelized'
viper.fromCamelCase('someJavascriptProperty', '_'); // 'some_javascript_property'mask
用指定的字符替换除最后指定个字符以外的所有字符
viper.mask = (str, num = 4, mask = '*') => {
return ('' + str).slice(0, -num).replace(/./g, mask) + ('' + str).slice(-num)
}viper.mask(1234567890); // '******7890'
viper.mask(1234567890, 3); // '*******890'
viper.mask(1234567890, -4, '$'); // '$$$$567890'palindrome
检查回文
viper.palindrome = (str) => {
const s = str.toLowerCase().replace(/[\W_]/g, '')
return (
s === s.split().reverse().join('')
)
}viper.palindrome('taco cat'); // truereverseString
反转字符串
viper.reverseString = (str) => [...str].reverse().join('')viper.reverseString('viper') // repivsortString
按字母顺序排列字符串中的字符
viper.sortString = (str) => [...str].sort((a, b) => a.localeCompare(b)).join('')viper.sortString('cabbage'); // 'aabbceg'toCamelCase
将字符串改为驼峰字符串
viper.toCamelCase = (str) => {
let s =
str &&
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())
.join('');
return s.slice(0, 1).toLowerCase() + s.slice(1)
}viper.toCamelCase('some_database_field_name'); // 'someDatabaseFieldName'
viper.toCamelCase('Some label that needs to be camelized'); // 'someLabelThatNeedsToBeCamelized'
viper.toCamelCase('some-javascript-property'); // 'someJavascriptProperty'truncateString
截断字符串在后面添加…
viper.truncateString = (str, num) => {
return str.length > num ? str.slice(0, num > 3 ? num -3 : num) + '...' : str
}truncateString('boomerang', 7); // 'boom...'unescapeHTML
反转义HTML字符串
viper.unescapeHTML = (str) => str.replace(
/&|<|>|'|"/g,
tag =>
({
'&': '&',
'<': '<',
'>': '>',
''': "'",
'"': '"'
}[tag] || tag)
)viper.unescapeHTML('<a href="#">Me & you</a>'); // '<a href="#">Me & you</a>'TYPE
digitize
校验字符是否是json
viper.isValidJSON = obj => {
try {
JSON.parse(obj)
} catch (e) {
return false
}
}viper.isValidJSON('{"name":"Adam","age":20}'); // true
viper.isValidJSON('{"name":"Adam",age:"20"}'); // false
viper.isValidJSON(null); // truegetType
获取类型 undefined、null、NaN 直接返回 其他返回小写的构造函数的名称
viper.getType = v => v !== v ? 'NaN' : v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase()viper.getType(new Set([1, 2, 3])); // 'set'
viper.getType({}) // object
viper.getType([]) // arrayUTILITY
coalesce
返回第一个非null非undefined的值
viper.coalesce = (...args) => args.find( _ => ![undefined, null].includes(_))viper.coalesce(null, undefined, '', NaN, 'Waldo'); // ""coalesceFactory
返回第一个符合过滤函数的值
viper.coalesceFactory = valid => (...args) => args.find(valid)const customCoalesce = coalesceFactory(_ => ![null, undefined, '', NaN].includes(_));
viper.customCoalesce(undefined, null, NaN, '', 'Waldo'); // "Waldo"extendHex
将3位数的hex颜色值转换成6为数的值
viper.extendHex = shortHex => '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(x => x + x ).join('')viper.extendHex('#03f'); // '#0033ff'getURLParams
返回对象包含url上的参数
viper.getURLParams = url => url.match(/([^?=&]+)(=([^&]*))/g).reduce(
(a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1 )),a), {}
)viper.getURLParams('http://url.com/page?name=Adam&surname=Smith'); // {name: 'Adam', surname: 'Smith'}hexToRGB
hex转rgb
viper.hexToRGB = hex => {
let alpha = false,
h = hex.slice(hex.startsWith('#') ? 1 : 0);
if (h.length === 3) h = [...h].map(x => x + x).join('');
else if (h.length === 8) alpha = true;
h = parseInt(h, 16);
return (
'rgb' +
(alpha ? 'a' : '') +
'(' +
(h >>> (alpha ? 24 : 16)) +
', ' +
((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
', ' +
((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
(alpha ? `, ${h & 0x000000ff}` : '') +
')'
);
}viper.hexToRGB('#27ae60ff'); // 'rgba(39, 174, 96, 255)'
viper.hexToRGB('27ae60'); // 'rgb(39, 174, 96)'
viper.hexToRGB('#fff'); // 'rgb(255, 255, 255)'randomHexCode
随机生成hex颜色值
viper.randomHexCode = () => {
let n = ((Math.random() * 0xfffff) | 0).toString(16)
return '#' + (n.length !== 6 ? ((Math.random() * 0xf) | 0).toString(16) + n : n)
}viper.randomHexCode() // "#e34155"RGBToHex
RGB转hex色值
viper.RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0')viper.RGBToHex(255, 165, 1); // 'ffa501'timeTaken
返回函数运行时长
viper.timeTaken = callback => {
console.time('timeTaken')
const cb = callback()
console.timeEnd('timeTaken')
return cb
}viper.timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375msUUIDGeneratorBrowser
使用crypto API 生成UUID 符合RFC4122 版本 4
viper.UUIDGeneratorBrowser = () => {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
)
}viper.UUIDGeneratorBrowser() // '7982fcfe-5721-4632-bede-6000885be57d'validEmail
邮箱验证
viper.validEmail = str => /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str)viper.validEmail('mymail@gmail.com') // true