J - Z 系列
获取数组元素下标(findIndex的实现)
const linearSearch = (arr, item) => {
for (const i in arr) {
if (arr[i] === item) return +i;
}
return -1;
};
linearSearch([2, 9, 9], 9); // 1
linearSearch([2, 9, 9], 7); // -1
// 只返回数组中的第一个
绑定事件一次(前面也有类似函数)
const listenOnce = (el, evt, fn) =>
el.addEventListener(evt, fn, { once: true });
// 可以传入 option(对象) 也可以传入 useCapture(布尔)
listenOnce(
document.getElementById('my-id'),
'click',
() => console.log('Hello world')
); // 'Hello world' will only be logged on the first click
给定键值对,转换为对象
const objectFromPairs = arr =>
// 结构赋值,直接获取了 key和value
arr.reduce((a, [key, val]) => ((a[key] = val), a), {});
objectFromPairs([['a', 1], ['b', 2]]); // {a: 1, b: 2}
检测用户是否是暗黑模式
const prefersDarkColorScheme = () =>
window &&
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches;
prefersDarkColorScheme(); // true
将字节单位大小转换为 KB,MB等
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];
};
prettyBytes(1000); // '1 KB'
prettyBytes(-27145424323.5821, 5); // '-27.145 GB'
prettyBytes(123456789, 3, false); // '123MB'
返回提供日期的季度
const quarterOfYear = (date = new Date()) => [
Math.ceil((date.getMonth() + 1) / 3),
date.getFullYear()
];
quarterOfYear(new Date('07/10/2018')); // [ 3, 2018 ]
quarterOfYear(); // [ 4, 2020 ]
将url问号后参数转换为键值对
const queryStringToObject = url =>
[...new URLSearchParams(url.split('?')[1])].reduce(
(a, [k, v]) => ((a[k] = v), a),
{}
);
queryStringToObject('https://google.com?page=1&count=10');
// {page: '1', count: '10'}
数组快速排序
const quickSort = arr => {
const a = [...arr];
if (a.length < 2) return a;
// 向下取整
const pivotIndex = Math.floor(arr.length / 2);
const pivot = a[pivotIndex];
const [lo, hi] = a.reduce(
(acc, val, i) => {
if (val < pivot || (val === pivot && i != pivotIndex)) {
acc[0].push(val);
} else if (val > pivot) {
acc[1].push(val);
}
return acc;
},
[[], []]
);
return [...quickSort(lo), pivot, ...quickSort(hi)];
};
quickSort([1, 6, 1, 5, 3, 2, 1, 4]); // [1, 1, 1, 2, 3, 4, 5, 6]
生成指定长度随机字符串
const randomAlphaNumeric = length => {
let s = '';
Array.from({ length }).some(() => {
s += Math.random().toString(36).slice(2);
return s.length >= length;
});
return s.slice(0, length);
};
randomAlphaNumeric(5); // '0afad'
随机16进制颜色
const randomHexColorCode = () => {
let n = (Math.random() * 0xfffff * 1000000).toString(16);
return '#' + n.slice(0, 6);
};
randomHexColorCode(); // '#e34155'
随机范围数组
const randomIntArrayInRange = (min, max, n = 1) =>
Array.from(
{ length: n },
() => Math.floor(Math.random() * (max - min + 1)) + min
);
randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]
随机数
const randomIntegerInRange = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
randomIntegerInRange(0, 5); // 2
创建一个生成器,该生成器使用给定的步长生成给定范围内的所有值
const rangeGenerator = function* (start, end, step = 1) {
let i = start;
while (i < end) {
yield i;
i += step;
}
};
// for of 用于遍历集合 (迭代器对象)
for (let i of rangeGenerator(6, 10)) console.log(i);
// Logs 6, 7, 8, 9
requestAnimationFrame 动画帧的形式,调用回调,同时提供取消方法
const recordAnimationFrames = (callback, autoStart = true) => {
let running = false,
raf;
const stop = () => {
if (!running) return;
running = false;
cancelAnimationFrame(raf);
};
const start = () => {
if (running) return;
running = true;
run();
};
const run = () => {
raf = requestAnimationFrame(() => {
callback();
if (running) run();
});
};
if (autoStart) start();
return { start, stop };
};
const cb = () => console.log('Animation frame fired');
const recorder = recordAnimationFrames(cb);
// logs 'Animation frame fired' on each animation frame
recorder.stop(); // stops logging
recorder.start(); // starts again
const recorder2 = recordAnimationFrames(cb, false);
// `start` needs to be explicitly called to begin recording frames
根据提供函数,过滤数组对象,并且保留需要的键值对
const 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
}
];
reducedFilter(data, ['id', 'name'], item => item.age > 24);
// [{ id: 2, name: 'mike'}]
// 有点意思,将保留的键数组,利用reduce再重组下
回到顶部,带动画
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
};
// requestAnimationFrame api的运用,同时可以扩展(滚动到指定元素或者其他方向)
// c - c / 8 距离的计算可以学习下(类似缓动动画?)
数组打乱顺序
const 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];
shuffle(foo); // [2, 3, 1], foo = [1, 2, 3]
去掉html标签
const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');
stripHTMLTags('<p><em>lorem</em> <strong>ipsum</strong></p>'); // 'lorem ipsum'
reduce的求和
const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
sum(1, 2, 3, 4); // 10
sum(...[1, 2, 3, 4]); // 10