希望这些示例能给你带来帮助,这些方法使用了一些API,简化了操作,有的柑橘处理的不咋优雅,但我们可以学习它的API使用技巧。
一、数组相关
1、数值类型转数组
- JS版本
const castArray = (value) => (Array.isArray(value) ? value : [value]); castArray(1); // [1]
- TS版本
const castArray = <T,_>(value: T | T[]): T[] => (Array.isArray(value) ? value : [value]); castArray(1); // [1]
2、校验数组是否为空
- JS版本
const isEmpty = (arr) => Array.isArray(arr) && !arr.length; isEmpty([]); // true
- TS版本
const isEmpty = <T,_>(arr: T[]): boolean => Array.isArray(arr) && !arr.length; isEmpty([1, 2, 3]); // false
3、将对象数组转为单个对象
- JS版本
const toObject = (arr, key) => arr.reduce((a, b) => ({ ...a, [b[key]]: b }), { }); //Or const toObject = (arr, key) => Object.fromEntries(arr.map((it) => [it[key], it]));
- TS版本
const toObject = <T extends Record<string, any>, K extends keyof T>(arr: T[], key: K): Record<string, T> => ( arr.reduce((a, b) => ({ ...a, [b[key]]: b }), { }) ); // Or const toObject = <T extends Record<string, any>, K extends keyof T>(arr: T[], key: K): Record<string, T> => ( Object.fromEntries(arr.map((it) => [it[key], it])) );
- 示例
toObject( [ { id: '1', name: 'Alpha', gender: 'Male' }, { id: '2', name: 'Bravo', gender: 'Male' }, { id: '3', name: 'Charlie', gender: 'Female' }, ], 'id' ); /* { '1': { id: '1', name: 'Alpha', gender: 'Male' }, '2': { id: '2', name: 'Bravo', gender: 'Male' }, '3': { id: '3', name: 'Charlie', gender: 'Female' }, } */
4、两个数组比较
- JS版本
// `a` and `b` are arrays const isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b); //Or const isEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]); isEqual([1, 2, 3], [1, 2, 3]); // true
- TS版本
const isEqual = <T,_>(a: T[], b: T[]): boolean => JSON.stringify(a) === JSON.stringify(b); //Or const isEqual = <T,_>(a: T[], b: T[]): boolean => a.length === b.length && a.every((v, i) => v === b[i]); isEqual([1, 2, 3], [1, '2', 3]); // false
5、将字符串数组转为数字
- JS版本
const toNumbers = (arr) => arr.map(Number); // Or const toNumbers = (arr) => arr.map((x) => +x); toNumbers(['2', '3', '4']); // [2, 3, 4]
- TS版本
const toNumbers = (arr: string[]): number[] => arr.map(Number); // Or const toNumbers = (arr: string[]): number[] => arr.map((x) => +x); toNumbers(['2', '3', '4']); // [2, 3, 4]
6、统计一个值在数组出现的次数
- JS版本
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); //Or const countOccurrences = (arr, val) => arr.filter((item) => item === val).length; countOccurrences([2, 1, 3, 3, 2, 3], 2); // 2
- TS版本
const countOccurrences = <T,_>(arr: T[], val: T): number => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); // Or const countOccurrences = <T,_>(arr: T[], val: T): number => arr.filter((item) => item === val).length; countOccurrences(['a', 'b', 'a', 'c', 'a', 'b'], 'a'); // 3
二、日期处理
1、两个日期相差月份
- JS版本
const monthDiff = (startDate, endDate) => Math.max(0, (endDate.getFullYear() - startDate.getFullYear()) * 12 - startDate.getMonth() + endDate.getMonth()); monthDiff(new Date('2020-01-01'), new Date('2021-01-01')); // 12
- TS版本
const monthDiff = (startDate: Date, endDate: Date): number => Math.max(0, (endDate.getFullYear() - startDate.getFullYear()) * 12 - startDate.getMonth() + endDate.getMonth()); monthDiff(new Date('2020-01-01'), new Date('2021-01-01')); // 12
2、两个日期比较
- JS版本
// `a` and `b` are `Date` instances const compare = (a, b) => a.getTime() > b.getTime(); compare(new Date('2020-03-30'), new Date('2020-01-01')); // true
- TS版本
const compare = (a: Date, b: Date): boolean => a.getTime() > b.getTime(); compare(new Date('2020-03-30'), new Date('2020-01-01')); // true
3、查找日期位于一年中的第几天
- JS版本
// `date` is a Date object const dayOfYear = (date) => Math.floor((date - new Date(date.getFullYear(), 0, 0)) / (1000 * 60 * 60 * 24)); dayOfYear(new Date(2020, 04, 16)); // 137
- TS版本
const dayOfYear = (date: Date): number => Math.floor((date.valueOf() - new Date(date.getFullYear(), 0, 0).valueOf()) / (1000 * 60 * 60 * 24)); dayOfYear(new Date(2020, 04, 16)); // 137
4、计算两个日期相差天数
- JS版本
const diffDays = (date, otherDate) => Math.ceil(Math.abs(date - otherDate) / (1000 * 60 * 60 * 24)); diffDays(new Date('2023-02-19'), new Date('2023-02-01')); //18
- TS版本
const diffDays = (date: Date, otherDate: Date): number => Math.ceil(Math.abs(date.valueOf() - otherDate.valueOf()) / (1000 * 60 * 60 * 24)); diffDays(new Date('2014-12-19'), new Date('2020-01-01')); // 1839
5、计算当前时间月份最后一天
- JS版本
const getLastDate = (d = new Date()) => new Date(d.getFullYear(), d.getMonth() + 1, 0);
- TS版本
const getLastDate = (d = new Date()): Date => new Date(d.getFullYear(), d.getMonth() + 1, 0);
6、是否为周末
- JS版本
const isWeekend = (date = new Date()) => date.getDay() % 6 === 0; isWeekend(new Date('2023-02-05'));// true
- TS版本
const isWeekend = (date = new Date()): boolean => date.getDay() % 6 === 0; isWeekend(new Date('2021-02-05'));// false
7、是否为工作日
- JS版本
const isWeekday = (date = new Date()) => date.getDay() % 6 !== 0;
- TS版本
const isWeekday = (date = new Date()): boolean => date.getDay() % 6 !== 0;
8、是否为闰年
- JS版本
const isLeapYear = (year) => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; //Or const isLeapYear = (year) => new Date(year, 1, 29).getDate() === 29;
- TS版本
const isLeapYear = (year: number): boolean => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; //Or const isLeapYear = (year: number): boolean => new Date(year, 1, 29).getDate() === 29;
三、数字相关操作
1、指定位数四舍五入
- JS版本
const round = (n, decimals = 0) => Number(`${ Math.round(`${ n}e${ decimals}`)}e-${ decimals}`); round(3.1415926,4);//3.1416
- TS版本
const round = (n: number, decimals: number = 0): number => Number(`${ Math.round(`${ n}e${ decimals}`)}e-${ decimals}`); round(1.234567, 4); //1.2346
2、指定位数小数(不四舍五入)
- JS版本
const toFixed = (n, fixed) => `${ n}`.match(new RegExp(`^-?\\d+(?:\.\\d{0,${ fixed}})?`))[0]; //Or const toFixed = (n, fixed) => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed); toFixed(25.198726354, 3); // 25.198
- TS版本
const toFixed = (n: number, fixed: number): number => +(`${ n}`.match(new RegExp(`^-?\\d+(?:\.\\d{0,${ fixed}})?`)) as string[])[0]; //Or const toFixed = (n: number, fixed: number): number => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed); toFixed(25.198726354, 6); // 25.198726
3、获取一组数的平均数
- JS版本
const average = (...args) => args.reduce((a, b) => a + b) / args.length; average(1, 2, 3, 4); // 2.5
- TS版本
const average = (...args: number[]): number => args.reduce((a, b) => a + b) / args.length; average(6,7,9,8);// 7.5
4、是否为偶数
- JS版本
const isEven = (n) => n % 2 === 0; //Or const isEven = (n) => (n & 1) === 0; //Or const isEven = (n) => !(n & 1); //Or const isEven = (n) => Number.isInteger(n / 2); isEven(1); // false
- TS版本
const isEven = (n: number): boolean => n % 2 === 0; //Or const isEven = (n: number): boolean => (n & 1) === 0; //Or const isEven = (n: number): boolean => !(n & 1); //Or const isEven = (n: number): boolean => Number.isInteger(n / 2); isEven(2); // true
四、DOM操作相关
1、检测元素是否聚焦
- JS版本
const hasFocus = (ele) => ele === document.activeElement;
- TS版本
const hasFocus = (ele: Node): boolean => ele === document.activeElement;
2、检测MacOS浏览器
- JS版本
const isMacBrowser = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
- TS版本
const isMacBrowser: boolean = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
3、检测页面是否滑到底部
- JS版本
const isAtBottom = () => document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight;
- TS版本
const isAtBottom = (): boolean => document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight;
4、在某个元素插入另一个元素
- JS版本
const insertAfter = (ele, anotherEle) => anotherEle.parentNode.insertBefore(ele, anotherEle.nextSibling); //Or const insertAfter = (ele, anotherEle) => anotherEle.insertAdjacentElement('afterend', ele);
- TS版本
const insertAfter = (ele: Element, anotherEle: Element): Element | null => (anotherEle.parentNode ? anotherEle.parentNode.insertBefore(ele, anotherEle.nextSibling) : null); //Or const insertAfter = (ele: Element, anotherEle: Element): Element | null => anotherEle.insertAdjacentElement('afterend', ele);
五、字符串相关
1、首字母大写
- JS版本
const capitalize = (str) => `${ str.charAt(0).toUpperCase()}${ str.slice(1)}`; //Or const capitalize = ([first, ...rest]) => `${ first.toUpperCase()}${ rest.join('')}`; //Or const capitalize = (str) => str.replace(/^([a-z])/, (first) => first.toUpperCase()); capitalize('hello world'); // 'Hello world'
- TS版本
const capitalize = (str: string): string => `${ str.charAt(0).toUpperCase()}${ str.slice(1)}`; //Or const capitalize = ([first, ...rest]: string): string => `${ first.toUpperCase()}${ rest.join('')}`; //Or const capitalize = (str: string): string => str.replace(/^([a-z])/, (first) => first.toUpperCase()); capitalize('hello world'); // 'Hello world'
2、判断是否为相对路径
- JS版本
const isRelative = (path) => !/^([a-z]+:)?[\\/]/i.test(path); isRelative('/foo/bar/baz'); // false isRelative('C:\\foo\\bar\\baz'); // false
- TS版本
const isRelative = (path: string): boolean => !/^([a-z]+:)?[\\/]/i.test(path); isRelative('foo/bar/baz.txt'); // true isRelative('foo.md'); // true
3、判断是否为绝对路径
- JS版本
const isAbsoluteUrl = (url) => /^[a-z][a-z0-9+.-]*:/.test(url); isAbsoluteUrl('https://1loc.dev'); // true isAbsoluteUrl('https://1loc.dev/foo/bar'); // true
- TS版本
const isAbsoluteUrl = (url: string): boolean => /^[a-z][a-z0-9+.-]*:/.test(url); isAbsoluteUrl('1loc.dev'); // false isAbsoluteUrl('//1loc.dev'); // false
4、字符反转
- JS版本
const reverse = (str) => str.split('').reverse().join(''); //Or const reverse = (str) => [...str].reverse().join(''); //Or const reverse = (str) => str.split('').reduce((rev, char) => `${ char}${ rev}`, ''); //Or const reverse = (str) => (str === '' ? '' : `${ reverse(str.substr(1))}${ str.charAt(0)}`); reverse('hello world'); // 'dlrow olleh'
- TS版本
const reverse = (str: string): string => str.split('').reverse().join(''); //Or const reverse = (str: string): string => [...str].reverse().join(''); //Or const reverse = (str: string): string => str.split('').reduce((rev, char) => `${ char}${ rev}`, ''); //Or const reverse = (str: string): string => (str === '' ? '' : `${ reverse(str.substr(1))}${ str.charAt(0)}`); reverse('hello world'); // 'dlrow olleh'
5、字符串复制N遍
- JS版本
const repeat = (str, numberOfTimes) => str.repeat(numberOfTimes); // Or const repeat = (str, numberOfTimes) => Array(numberOfTimes + 1).join(str); repeat('abc',2);//abcabc
- TS版本
const repeat = (str: string, numberOfTimes: number): string => str.repeat(numberOfTimes); //Or const repeat = (str: string, numberOfTimes: number): string => Array(numberOfTimes + 1).join(str); repeat('adf',2);//adfadf
6、Windows路径转Unix路径
- JS版本
const toUnixPath = (path) => path.replace(/[\\/]+/g, '/').replace(/^([a-zA-Z]+:|\.\/)/, ''); toUnixPath('./foo/bar/baz'); // foo/bar/baz
- TS版本
const toUnixPath = (path: string): string => path.replace(/[\\/]+/g, '/').replace(/^([a-zA-Z]+:|\.\/)/, ''); toUnixPath('C:\\foo\\bar\\baz'); // /foo/bar/baz
7、ANSI转String
- JS版本
const stripAnsiCodes = (str) => str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''); stripAnsiCodes('\u001B[4mcake\u001B[0m'); // 'cake'
- TS版本
const stripAnsiCodes = (str: string): string => str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''); stripAnsiCodes('\u001B[0m\u001B[4m\u001B[42m\u001B[31mfoo\u001B[39m\u001B[49m\u001B[24mfoo\u001B[0m'); // 'foofoo'
8、字符串Hash
- JS版本
const hash = (str) => str.split('').reduce((prev, curr) => (Math.imul(31, prev) + curr.charCodeAt(0)) | 0, 0); //Or const hash = (str) => str.split('').reduce((prev, curr) => ((prev << 5) - prev + curr.charCodeAt(0)) | 0, 0); hash('hello world');// 1794106052
- TS版本
const hash = (str: string): number => str.split('').reduce((prev, curr) => (Math.imul(31, prev) + curr.charCodeAt(0)) | 0, 0); //Or const hash = (str: string): number => str.split('').reduce((prev, curr) => ((prev << 5) - prev + curr.charCodeAt(0)) | 0, 0); hash('hello');// 99162322
9、字符串转大驼峰命名
- JS版本
const toPascalCase = (str) => (str.match(/[a-zA-Z0-9]+/g) || []).map((w) => `${ w.charAt(0).toUpperCase()}${ w.slice(1)}`).join(''); toPascalCase('hello world'); // 'HelloWorld'
- TS版本
const toPascalCase = (str: string): string => (str.match(/[a-zA-Z0-9]+/g) || []).map((w) => `${ w.charAt(0).toUpperCase()}${ w.slice(1)}`).join(''); toPascalCase('hello.world'); // 'HelloWorld' toPascalCase('foo_bar-baz'); // FooBarBaz
10、是否包含小写字符
- JS版本
const containsLowerCase = (str) => str !== str.toUpperCase(); containsLowerCase('Hello World'); // true
- TS版本
const containsLowerCase = (str: string): boolean => str !== str.toUpperCase(); containsLowerCase('HELLO WORLD'); // false
六、其他
1、UUID
- JS版本
const uuid = (a) => (a ? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16) : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid));
2、随机IP地址
- JS版本
const randomIp = () => Array(4) .fill(0) .map((_, i) => Math.floor(Math.random() * 255) + (i === 0 ? 1 : 0)) .join('.');
- TS版本
const randomIp = (): number => Array(4) .fill(0) .map((_, i) => Math.floor(Math.random() * 255) + (i === 0 ? 1 : 0)) .join('.');
3、随机颜色
- JS版本
const randomColor = () => `#${ Math.random().toString(16).slice(2, 8).padEnd(6, '0')}`; //Or const randomColor = () => `#${ (~~(Math.random() * (1 << 24))).toString(16)}`;
- TS版本
const randomColor = (): string => `#${ Math.random().toString(16).slice(2, 8).padEnd(6, '0')}`; //Or const randomColor = (): string => `#${ (~~(Math.random() * (1 << 24))).toString(16)}`;
4、生成N位字符串(数字字符)
- JS版本
const generateString = (length, chars) => Array(length) .fill('') .map((v) => chars[Math.floor(Math.random() * chars.length)]) .join(''); generateString(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');// a2ZwXLBqwI
- TS版本
const generateString = (length: number, chars: string) => Array(length) .fill('') .map((v) => chars[Math.floor(Math.random() * chars.length)]) .join('');