前言,这是对github上30sCode片段的整理,点击查看github上的地址。
1、Array 篇
Use Array.prototype.every() to test if all elements in the collection return true based on fn
const all = (arr, fn = Boolean) => arr.every(fn);
// example
all([4,2,1], x => x > 1); // true
Use Array.prototype.some() to test if any elements in the collection return true based on fn
const any = (arr, fn = Boolean) => arr.some(fn)
// example
any([0,1,0,0]) ; // true
☆ bifurcateBy 分叉的 利用fn 对数组进行数据切分
Use Array.prototype.reduce() and Array.prototype.push() to add elements to groups, based on the value returned by fn for each element.
const bifurcateBy = (arr, fn) => arr.reduce((acc, val, i) => (acc[fn(val,i)?0:1].push(val),acc), [[],[]])
// example
bifurcateBy(['beep', 'boop', 'foo', 'bar'] , x => x[0] === 'b'); // [ ['beep', 'boop', 'bar'], ['foo'] ]
☆ chunk
Chunks an array into smaller arrays of a specified size.
const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);
// example
chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
Array.from({length:5},callback) // ['undefined','undefined','undefined','undefined','undefined']
compact
Removes falsey values from an array 。use Array.prototype.filter()
const compact = arr => arr.filter(Boolean)
// example
compact([0,1,false,2,'23','0']) // [1, 2, "23", "0"]
☆ countBy
对数组的元素进行个数统计,通过fn 规则来。
const countBy = (arr, fn) =>
arr.map(typeof fn ==='function'? fn : val => val[fn]).reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
},{})
// example
countBy(['5.1','4.2','3.1'], Math.floor) // {3: 1, 4: 1, 5: 1}
countOccurrences 元素统计。利用reduce
Counts the occurrences of a value in an array。 计数
const countOccurrences = (arr, val) => arr.reduce((a,v) => (v===val ? a+1:a ),0)
// example
countOccurrences([1,2,3,4,1,2,2],2) // 3
☆ deepFlatten (深解)
解套
the spread operator (…) to flatten an array ☆
const deepFlatten = arr => [].concat( ...arr.map(v => ( Array.isArray(v) ? deepFlatten(v) : v )) )
// example
deepFlatten([1,2,[3],4,[3,3,[2]]]) // [1, 2, 3, 4, 3, 3, 2]
difference
找出数组中与第一个arr不同的元素.
const difference = (a, b) => {
const s = new Set(b);
return a.filter( x => !s.has(x))
// return a.filter( x => s.has(x) ) // 找出相同的
}
// example
difference([1,2,3,55],[2,3,1,4])
differenceBy
经过fn处理之后,再进行difference 处理。
const differenceBy = (a, b, fn) => {
const s = new Set(b.map(fn));
return a.filter( x => !s.has( fn(x)));
}
// example
differenceBy([2.1,1.2],[2.3,3.4], Math.floor ) ; // [1.2]
differenceBy( [{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x ); // [{ x : 2 }]
findLast
满足fn ,里的最后一个
const findLast = (arr, fn) => arr.filter(fn).pop();
// example
findLast( [1,2,3,4], n => n % 2 === 1 ); // 3
initialize2DArray
初始化2d 数组
const initialize2DArray = (w, h, val = null) =>
Array.from({length:h}).map( () => Array.from({ length:w }).fill(val ));
// example
initialize2DArray(2,2,0) // [[0,0],[0,0]]
nthElement
return the nth element of an array.
返回指定index的元素。
const nthElement = (arr, n=0) => ( n=== -1 ? arr.slice(n) : arr.slice(n,n+1) )[0]
// example
nthElement(['a','b','c'], 1); // 'b'
nthElement(['a', 'b', 'b'], -3); // 'a'
similarity
return an array of elements that appear in both arrys 交集
const similarity = (arr, values) => arr.filter( v => values.includes(v));
// example
similarity([1,2,3],[1,2,4]); // [1,2]
union 并集
const union = (a, b) => Array.from( new Set([...a,...b]));
const uniqueElements = arr => [...new Set(arr)];
// example
union([1,2,3],[3,4,2,3])
uniqueElementsBy
对象去重 reduce
const uniqueElementsBy = (arr, fn) =>
arr.reduce((acc,v) => {
if( !acc.some( x => fn(v, x) ) ) acc.push(v)
return acc;
},[]);
// example
uniqueElementsBy(
[
{ id: 0, value: 'a' },
{ id: 1, value: 'b' },
{ id: 2, value: 'c' },
{ id: 1, value: 'd' },
{ id: 0, value: 'e' }
],
(a, b) => a.id == b.id
); // [ { id: 0, value: 'a' }, { id: 1, value: 'b' }, { id: 2, value: 'c' } ]
uniqueElementsByRight
const uniqueElementsByRight = (arr, fn) =>
arr.reduceRight( (acc, v) => {
if( !acc.some( x => fn( v, x ) ) ) acc.push(v);
return acc;
} , []);
uniqueElementsByRight(
[
{ id: 0, value: 'a' },
{ id: 1, value: 'b' },
{ id: 2, value: 'c' },
{ id: 1, value: 'd' },
{ id: 0, value: 'e' }
],
(a, b) => a.id == b.id
);
// [ { id: 0, value: 'e' }, { id: 1, value: 'd' }, { id: 2, value: 'c' } ]
without …args
filter out the elements of an array, that have one of the specified values
const without = (arr, ...args) => arr.filter( v => !args.includes(v) );
// example
without([2,1,2,3], 1,2) // [3]
unzip
create an array of arrays, ungruoping the element in an arrya produced by zip
const unzip = arr =>
arr.reduce(
(acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
Array.from({
length: Math.max( ...arr.map( x => x.length ) )
}).map(x => [])
);
// example
unzip([['a', 1, true], ['b', 2, false]]); // [['a', 'b'], [1, 2], [true, false]]
unzip([['a', 1, true], ['b', 2]]); // [['a', 'b'], [1, 2], [true]]
2、Browser 篇
elementCointains 父节点是否含有子节点
const elementContains = (parent, child) => parent !== child && parent.contains(child)
elementIsVisibleInViewport
检测默个元素是否完全可见 、或者部分可见
// partiallyVisible 为true 代表部分可见检测
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 && letf < innerWidth) || (right > 0 && right < innerWidth)) : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth
}
httpsRedirect http 转成https location.replace 本页自动刷新
const httpsRedirect = ()=> {
if( location.protocol !== 'https:' ) location.replace('https://'+ location.href.split('//')[1])
}
原生hasClass实现。 用到了contains
const hasClass = (el, className) => el.classList.contains( className )
isBrowserTabFocused
检测当前页是否在本tab上
const isBrowserTabFocused = () => !document.hidden
scrollTop
快速回到顶部 requestAnimationFrame 调用一次走一次
const scrollTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if( c > 0 ){
window.requestAnimationFrame( scrollTop )
window.scrollTop(0, c - c / 8)
}
}
smoothScroll ☆ scrollIntoview
快速将某个元素滚动到视野中
const smoothScroll = element =>
document.querySelector( element ).scrollIntoview({
behavior: 'smooth'
})
CustomEvent 自定义事件
function createEvent(params, eventName = 'mock-event') {
return new CustomEvent(eventName, { detail: params })
}
const event = createEvent({ id: '0010' })
window.addEventListener('mock-event', ({ detail: { id } }) => {
console.log('id', id) // 会在控制台打印0010
});
window.dispatchEvent(event)
3、Function 篇
☆ sleep
delays the execution of an asynchronous function
const sleep = ms => new Promise( resolve => setTimeout(resolve, ms) );
// example
async function sleepwork(){
consolelog('i am going to sleep for 1 second');
await sleep(1000);
console.log('等待了1s')
}
☆ throttle (节流函数)
const throttle = (fn, wait) => {
let inThrottle, lastFn, lastTime;
return function() {
const context = this,
args = arguments;
if (!inThrottle) {
fn.apply(context, args);
lastTime = Date.now();
inThrottle = true;
} else {
clearTimeout(lastFn);
lastFn = setTimeout(function() {
if (Date.now() - lastTime >= wait) {
fn.apply(context, args);
lastTime = Date.now();
}
}, Math.max(wait - (Date.now() - lastTime), 0));
}
};
};
// example
window.addEventListener(
'resize',
throttle(function(evt) {
console.log(window.innerWidth);
console.log(window.innerHeight);
}, 2500)
); // Will log the window dimensions at most every 2500ms
4、Math 篇
approximatelyEqual (近似相等)
检查两个数是否近似相等。
const approximatelyEqual = ( v1, v2, epsilon = 0.001 ) => Math.abs(v1 - v2) < epsilon ;
// example
approximatelyEqual( Math.PI / 2.0 , 1.5708 ) // true
average 取平均
const average = (...nums) => nums.reduce(( acc, val ) => acc + val , 0 ) / nums.length
// example
average(...[1,2,3]); // 2
average(1,2,3) // 2
averageBy fn之后取平均
const averageBy = (arr, fn) =>
arr.map( typeof fn === 'function' ? fn : val => val[fn] ).reduce( (acc, val) => acc + val , 0 ) / arr.length;
// example
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5
fibonacci
const fibonacci = n =>
Array.from({length: n}).reduce(
(acc, val, i) => acc.concat( i > 1 ? acc[i - 1] + acc[i -2] : i ), [] )
// example
fibonacci(6); // [0, 1, 1, 2, 3, 5]
sum 累加
const sum = (...arr) => [...arr].reduce( ( acc, val ) => acc + val , 0 );
// example
sum(...[1,2,3,4]) // 10
sumBy fn 后累加
const sumBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce( (acc, val) => acc + val, 0 )
// example
sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 20
sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 20
5、Object 篇
deepClone 深拷贝
还有一种方式就要JSON.stringify() JSON.parse() 也能实现深copy
const deepClone = obj => {
let clone = Object.assign({}, obj);
// 这一步已经实现了clone
Object.keys(clone).forEach(
key => ( clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key] )
);
return Array.isArray(obj) ? ( clone.length = obj.length ) && Array.from(clone) : clone ;
}
// example
// 通过改变默认value 是否影响到旧了来进行判定
☆ merge 合并对象,最终以数组形式展现
const 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;
}, {} )
, {} )
// example
const object = {
a: [{ x: 2 }, { y: 4 }],
b: 1
};
const other = {
a: { z: 3 },
b: [2, 3],
c: 'foo'
};
merge(object, other); // { a: [ { x: 2 }, { y: 4 }, { z: 3 } ], b: [ 1, 2, 3 ], c: 'foo' }
lowercaseKeys
创建一个object 并且lower 处理
const lowercaseKeys = obj =>
Object.keys( obj ).reduce( (acc, key) =>{
acc[key.toLowerCase()] = obj[key];
return acc;
}, {} )
// example
const myObj = { Name : 'Admin' , sUrnAme:'aa' }
const myObjLower = lowercaseKeys( myObj )
omit
删除指定key 之后,返回obj
const omit = (obj, arr) =>
Object.keys(obj)
.filter( k => !arr.includes(k) )
.reduce( ( acc, key) =>(( acc[key] = obj[key] ) ,acc ), {} );
// example
omit({ a: 1, b: '2', c: 3 }, ['b']); // { 'a': 1, 'c': 3 }
omitBy
const omitBy = (obj, fn) =>
Object.keys(obj)
.filter( k => !fn( obj[k] ,k ) )
.reduce( (acc, key) => ( (acc[key] = obj[key]), acc ) , {} );
// example
omitBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { b: '2' }
pick
const pick = ( obj, arr ) =>
arr.reduce( (acc, curr) => ( curr in obj && ( acc[curr] = obj[curr] ), acc ),{} )
// example
pick({ a: 1, b: '2', c: 3 }, ['a', 'c']); // { 'a': 1, 'c': 3 }
pickBy
const pickBy = (obj, fn) =>
Object.keys(obj)
.filter( k => fn( obj[k] , k) )
.reduce( (acc, key) => ( (acc[key] = obj[key]), acc ),{} )
// example
pickBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number');
size 返回数组or字符串,对象的长度
const 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 : 0 ;
// example
size([1, 2, 3, 4, 5]); // 5
size('size'); // 4
size({ one: 1, two: 2, three: 3 }); // 3
5、String 篇
byteSie
return the length of a string in bytes
const byteSize = str => new Blob([str]).size;
// example
byteSize('Hello') // 5
capitalizeEveryWord
格式化第一个字符 大写
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()) ;
// example
capitalizeEveryWord ( 'hello world' ); // hello world
escapeHTML
escape a string for use in HTML
const escapeHTML = str =>
str.replace( /[&<>'"]/g , tag =>
({
'&': '&',
'<': '<',
'>': '>',
" ' ": ''',
' " ': '$quot;'
}[tag] || tag)
);
// example
escapeHTML('<a href="#">Me & you</a>');
unescapeHTML
const unescapeHTML = str =>
str.replace(
/&|<|>|'|"/g,
tag =>
({
'&': '&',
'<': '<',
'>': '>',
''': "'",
'"': '"'
}[tag] || tag)
);
// example
unescapeHTML(’<a href="#">Me & you</a>’); // ‘Me & you’
mask
前多少位进行填充 padStart
const mask = (cc, num =4 , mask = '*') =>
`${cc}`.slice(-num).padStart( `${cc}`.length, mask );
// example
mask(1234567890); // '******7890'
mask(1234567890, 3); // '*******890'
mask(1234567890, -4, '$'); // '$$$$567890'
6、Type 篇
☆ isEmpty
检测是否为一个空的对象
const isEmpty = val => val == null || !( Object.keys(val) || val ).length;
// example
isEmpty(new Map()); // true
isEmpty(new Set()); // true
isEmpty([]); // true
isEmpty({}); // true
isEmpty(''); // true
isEmpty([1, 2]); // false
isEmpty({ a: 1, b: 2 }); // false
isEmpty('text'); // false
isEmpty(123); // true - type is not considered a collection
isEmpty(true); // true - type is not considered a collection
isObject
const isObject = obj => obj === Object(obj);
// example
isObject([1, 2, 3, 4]); // true
isObject([]); // true
isObject(['Hello!']); // true
isObject({ a: 1 }); // true
isObject({}); // true
isObject(true); // false
isPromiseLike
Returns true if an object looks like a Promise, false otherwise.
const isPromiseLike = obj =>
obj !== null &&
( typeof obj === 'object' || typeof obj === 'function' ) && typeof obj.then === 'function' ;
// example
isPromiseLike({
then: function() {
return '';
}
}); // true
isPromiseLike(null); // false
isPromiseLike({}); // false
isValidJSON json 是否可用
const isValidJSON = obj => {
try{
JSON.parse(obj)
return true;
}catch(e){
return false
}
}
// example
isValidJSON('{"name":"Adam","age":20}'); // true
isValidJSON('{"name":"Adam",age:"20"}'); // false
isValidJSON(null); // true
7、Utility 篇
☆getURLParameters
获取url 上的数据
const getURLParameters = url =>
(url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
(a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
{}
);
// example
getURLParameters('http://url.com/page?name=Adam&surname=Smith'); // {name: 'Adam', surname: 'Smith'}
getURLParameters('google.com'); // {}
isBrowser
检测是否是浏览器
const isBrowser = () => ![typeof window, typeof document].includes('undefined');
// example
isBrowser(); // true (browser)
parseCookie
const parseCookie = str =>
str
.split(';')
.map(v => v.split('='))
.reduce((acc, v) => {
acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
return acc;
}, {});
// example
parseCookie('foo=bar; equation=E%3Dmc%5E2');
prettyBytes
Converts a number in bytes to a human-readable string.
const prettyBytes = (num, precision = 3, addSpace = true) => {
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0];
const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1);
const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision));
return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent];
};
// example
prettyBytes(1000); // "1 KB"
prettyBytes(-27145424323.5821, 5); // "-27.145 GB"
prettyBytes(123456789, 3, false); // "123MB"
toDecimalMark
const toDecimalMark = num => num.toLocaleString('en-US');
// example
toDecimalMark(12305030388.9087); // "12,305,030,388.909"
validateNumber
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
// example
validateNumber('10'); // true
☆quickSort
const quickSort = ([n, ...nums], desc) =>
isNaN(n)
? []
: [
...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc),
n,
...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)
];
// example
quickSort([4, 1, 3, 2]); // [1,2,3,4]
quickSort([4, 1, 3, 2], true); // [4,3,2,1]
// 终于看了一遍。。。