大家好,我是阿瓜。一个励志想成为艾弗森的前端瓜 ~
我们已经分享了 radash
库中数组、对象等相关的方法,大家感兴趣的可以前往主页查看阅读;
或许你最近在某个地方听过或者看过 radash
这个词,它是一个typescript编写的方法库,如果你想试试使用它,我们有简单使用示例,直接套用类似情景使用即可,如果你想深入了解一下这个库,想阅读一下它的源码,我们也会带你逐行解析代码;不管是哪种,相信你都能在文章里有所收获;
后续所有方法分享完毕后,我们会整理一份详细目录文章以及思维导图,方便大家查阅使用。
使用说明
null
。使用代码示例
import { draw } from 'radash'
const fish = ['marlin', 'bass', 'trout']
draw(fish) // => a random fish
源码解析
// 定义一个泛型函数 `draw`。
export const draw = <T>(
// `array` 是一个只读数组,包含要从中抽取元素的元素。
array: readonly T[]
): T | null => {
// 获取数组的长度。
const max = array.length
// 如果数组为空(长度为0),返回 `null`。
if (max === 0) {
return null
}
// 使用 `random` 函数获取一个随机索引。该索引介于 0(包括)和数组长度减1(包括)之间。
const index = random(0, max - 1)
// 返回数组中该随机索引位置的元素。
return array[index]
}
draw
函数接受一个数组 array
作为参数。array
为空(长度为0),函数返回 null
。array
非空,函数调用 random
函数获取一个随机索引,该索引在数组的有效范围内。使用说明
使用代码示例
import { random } from 'radash'
random(0, 100) // => a random number between 0 and 100
源码解析
// 定义一个名为 `random` 的函数。
export const random = (min: number, max: number) => {
// 使用 `Math.random` 生成一个介于 0(包含)和 1(不包含)之间的随机数,
// 然后乘以 `(max - min + 1)` 使得结果分布在 `[min, max]` 的范围内。
// 最后,使用 `Math.floor` 向下取整,以确保结果是一个整数。
return Math.floor(Math.random() * (max - min + 1) + min)
}
方法流程说明:
random
函数接受两个数字参数 min
和 max
。Math.random()
生成一个随机浮点数,它的值在 0(包含)和 1(不包含)之间。(max - min + 1)
,扩展其范围到 [min, max]
。min
以调整范围的起点。Math.floor()
对结果进行向下取整,以确保返回值是介于 min
和 max
之间的一个整数。使用说明
使用代码示例
import { shuffle } from 'radash'
const fish = [
{
name: 'Marlin',
weight: 105,
source: 'ocean'
},
{
name: 'Salmon',
weight: 22,
source: 'river'
},
{
name: 'Salmon',
weight: 22,
source: 'river'
}
]
shuffle(fish)
源码解析
// 定义一个泛型函数 `shuffle`。
export const shuffle = <T>(array: readonly T[]): T[] => {
// 链式调用几个数组方法来打乱数组。
return array
// 首先,使用 `map` 方法将每个数组元素 `a` 转换为一个包含随机数和原始值的对象。
.map(a => ({ rand: Math.random(), value: a }))
// 接着,使用 `sort` 方法对这些对象进行排序。
// 排序依据是每个对象的 `rand` 属性,即之前生成的随机数。
.sort((a, b) => a.rand - b.rand)
// 最后,使用 `map` 方法将排序后的对象数组转换回原始值数组。
.map(a => a.value)
}
方法流程说明:
shuffle
函数接受一个数组 array
作为参数。map
方法生成一个新的数组,其中每个元素都是一个包含原始元素和一个随机数的对象。sort
方法对这个新数组进行排序。排序的依据是每个对象的随机数属性 rand
。map
方法提取排序后的对象数组中的原始值,并形成一个新的数组。使用说明
使用代码示例
import { uid } from 'radash'
uid(7) // => UaOKdlW
uid(20, '*') // => dyJdbC*NsEgcnGjTHS
源码解析
// 定义一个泛型函数 `iterate`。
export const iterate = <T>(
// `count` 是要执行的迭代次数。
count: number,
// `func` 是每次迭代调用的函数,它接受当前的值和迭代次数,并返回新的值。
func: (currentValue: T, iteration: number) => T,
// `initValue` 是迭代的初始值。
initValue: T
) => {
// 初始化 `value` 为初始值。
let value = initValue
// 使用 `for` 循环执行指定次数的迭代。
for (let i = 1; i <= count; i++) {
// 在每次迭代中,调用 `func` 函数并更新 `value`。
value = func(value, i)
}
// 返回最终的 `value`。
return value
}
// 定义一个名为 `uid` 的函数。
export const uid = (length: number, specials: string = '') => {
// 定义一个字符集,包含大小写字母、数字,以及可选的特殊字符。
const characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + specials
// 调用 `iterate` 函数生成随机字符串。
return iterate(
length,
// `iterate` 函数的第二个参数是一个累加器函数,它接受当前的累加值 `acc`。
acc => {
// 在每次迭代中,通过 `random` 函数获取 `characters` 中的一个随机字符,
// 并将其添加到累加值 `acc` 末尾。
return acc + characters.charAt(random(0, characters.length - 1))
},
// `iterate` 函数的第三个参数是初始累加值,这里是一个空字符串。
''
)
}
方法流程说明:
uid
函数接受 length
和可选的 specials
作为参数。characters
。iterate
方法生成随机字符串。iterate
函数接受三个参数:迭代次数、累加器函数和初始累加值。random
函数获取 characters
中的一个随机索引,并通过 charAt
方法获取对应的字符。acc
末尾。iterate
函数返回生成的随机字符串。使用说明
items
数组的方法。这些方法包括获取最小/最大元素、第一个/最后一个元素、下一个/前一个元素以及旋转数组中元素的位置。使用代码示例
import { series } from 'radash'
type Weekday = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday'
const weekdays = series<Weekday>([
'monday',
'tuesday',
'wednesday',
'thursday',
'friday'
])
weekdays.min('tuesday', 'thursday') // => 'tuesday'
weekdays.max('wednesday', 'monday') // => 'wednesday'
weekdays.next('wednesday') // => 'thursday'
weekdays.previous('tuesday') // => 'monday'
weekdays.first() // => 'monday'
weekdays.last() // => 'friday'
weekdays.next('friday') // => null
weekdays.next('friday', weekdays.first()) // => 'monday'
weekdays.spin('monday', 3) // => 'thursday'
源码解析
// 定义一个函数 `series`。
const series = (items, toKey = (item) => `${item}`) => {
// 使用 `reduce` 方法构建两个映射:一个是元素到索引的映射,另一个是索引到元素的映射。
const { indexesByKey, itemsByIndex } = items.reduce(
(acc, item, idx) => ({
indexesByKey: {
...acc.indexesByKey,
[toKey(item)]: idx
},
itemsByIndex: {
...acc.itemsByIndex,
[idx]: item
}
}),
{
indexesByKey: {},
itemsByIndex: {}
}
);
// 定义一个 `min` 函数,它返回两个元素中索引较小的元素。
const min = (a, b) => {
return indexesByKey[toKey(a)] < indexesByKey[toKey(b)] ? a : b;
};
// 定义一个 `max` 函数,它返回两个元素中索引较大的元素。
const max = (a, b) => {
return indexesByKey[toKey(a)] > indexesByKey[toKey(b)] ? a : b;
};
// 定义一个 `first` 函数,它返回数组中的第一个元素。
const first = () => {
return itemsByIndex[0];
};
// 定义一个 `last` 函数,它返回数组中的最后一个元素。
const last = () => {
return itemsByIndex[items.length - 1];
};
// 定义一个 `next` 函数,它返回当前元素的下一个元素,如果没有则返回默认值或第一个元素。
const next = (current, defaultValue) => {
return itemsByIndex[indexesByKey[toKey(current)] + 1] ?? defaultValue ?? first();
};
// 定义一个 `previous` 函数,它返回当前元素的前一个元素,如果没有则返回默认值或最后一个元素。
const previous = (current, defaultValue) => {
return itemsByIndex[indexesByKey[toKey(current)] - 1] ?? defaultValue ?? last();
};
// 定义一个 `spin` 函数,它根据 `num` 的值旋转当前元素的位置。
const spin = (current, num) => {
if (num === 0)
return current;
const abs = Math.abs(num);
const rel = abs > items.length ? abs % items.length : abs;
return list(0, rel - 1).reduce(
(acc) => num > 0 ? next(acc) : previous(acc),
current
);
};
// 返回一个包含所有定义好的方法的对象。
return {
min,
max,
first,
last,
next,
previous,
spin
};
};
方法流程说明:
series
接受一个数组 items
和一个可选的 toKey
函数作为参数。reduce
方法构建两个映射:indexesByKey
将每个元素的键映射到其在数组中的索引,itemsByIndex
将每个索引映射到对应的元素。items
数组,包括 min
、max
、first
、last
、next
、previous
和 spin
。min
和 max
方法用于比较两个元素的索引并返回索引较小或较大的元素。first
和 last
方法分别返回数组中的第一个和最后一个元素。next
和 previous
方法分别返回给定元素的下一个和前一个元素,如果不存在则返回默认值或第一个/最后一个元素。spin
方法根据给定的数量 num
旋转当前元素的位置,正数表示向后旋转,负数表示向前旋转。使用说明
str
转换为驼峰命名法(camelCase)。这个函数首先将字符串中的所有大写字母转换为小写,并在每个大写字母前添加一个空格,然后根据大写字母、点号、破折号、空格或下划线分割字符串,最后将分割出的字符串数组转换为驼峰式。使用代码示例
import { camel } from 'radash'
camel('green fish blue fish') // => greenFishBlueFish
源码解析
// 定义一个函数 `camel`。
export const camel = (str: string): string => {
// 使用一系列字符串方法处理输入字符串 `str`。
const parts =
str
// 使用 `replace` 方法将连续的大写字母转换为小写,并在每个大写字母前添加一个空格。
?.replace(/([A-Z])+/g, capitalize)
// 使用 `split` 方法根据大写字母或点号、破折号、空格、下划线分割字符串。
?.split(/(?=[A-Z])|[\.\-\s_]/)
// 使用 `map` 方法将每个字符串转换为小写。
.map(x => x.toLowerCase()) ?? []
// 如果处理后的字符串数组 `parts` 为空,则返回空字符串。
if (parts.length === 0) return ''
// 如果 `parts` 只有一个元素,则返回该元素。
if (parts.length === 1) return parts[0]
// 使用 `reduce` 方法将 `parts` 中的字符串组合成驼峰命名法。
return parts.reduce((acc, part) => {
// 将当前字符串 `part` 的首字母大写,然后将其与累加器字符串 `acc` 连接。
return `${acc}${part.charAt(0).toUpperCase()}${part.slice(1)}`
})
}
方法流程说明:
camel
函数接受一个字符串 str
作为参数。replace
方法将连续的大写字母转换为小写,并在每个大写字母前添加一个空格。split
方法根据大写字母或特殊字符分割字符串。map
方法将每个字符串转换为小写。parts
为空,则返回空字符串。parts
只有一个元素,则返回该元素。parts
有多个元素,使用 reduce
方法组合它们为驼峰命名法的字符串。使用说明
str
的首字母大写,其余字母小写。如果输入字符串为空或长度为0,则返回空字符串。使用代码示例
import { capitalize } from 'radash'
capitalize('green fish blue FISH') // => Green fish blue fish
源码解析
// 定义一个名为 `capitalize` 的函数。
export const capitalize = (str: string): string => {
// 检查输入字符串是否为空或长度为0,如果是,则返回空字符串。
if (!str || str.length === 0) return ''
// 将整个字符串转换为小写。
const lower = str.toLowerCase()
// 返回一个新字符串,其中首字母大写,其余部分为小写。
// 使用 `substring` 方法获取第一个字符并将其转换为大写,
// 然后将其与字符串的剩余部分(从第二个字符开始)连接起来。
return lower.substring(0, 1).toUpperCase() + lower.substring(1, lower.length)
}
方法流程说明:
capitalize
函数接受一个字符串 str
作为参数。str
是否为空或长度为0,如果是,则返回空字符串。substring
方法获取字符串的第一个字符,并使用 toUpperCase
方法将其转换为大写。substring
方法获取字符串的剩余部分(从第二个字符开始)。使用说明
str
转换为短横线命名法(kebab-case)。这个函数首先将字符串中的所有大写字母转换为小写,并在每个大写字母前添加一个短横线,然后根据大写字母、点号、破折号、空格或下划线分割字符串,最后将分割出的字符串数组转换为短横线命名法。使用代码示例
import { dash } from 'radash'
dash('green fish blue fish') // => green-fish-blue-fish
源码解析
// 定义一个名为 `dash` 的函数。
export const dash = (str: string): string => {
// 使用一系列字符串方法处理输入字符串 `str`。
const parts =
str
// 使用 `replace` 方法将连续的大写字母转换为小写,并在每个大写字母前添加一个短横线。
// 这里假设 `capitalize` 函数会进行相应的转换,但实际上这可能不是预期的行为。
?.replace(/([A-Z])+/g, capitalize)
// 使用 `split` 方法根据大写字母或点号、破折号、空格、下划线分割字符串。
?.split(/(?=[A-Z])|[\.\-\s_]/)
// 使用 `map` 方法将每个字符串转换为小写。
.map(x => x.toLowerCase()) ?? []
// 如果处理后的字符串数组 `parts` 为空,则返回空字符串。
if (parts.length === 0) return ''
// 如果 `parts` 只有一个元素,则返回该元素。
if (parts.length === 1) return parts[0]
// 使用 `reduce` 方法将 `parts` 中的字符串组合成短横线命名法。
return parts.reduce((acc, part) => {
// 将当前字符串 `part` 转换为小写,并用短横线连接到累加器字符串 `acc`。
return `${acc}-${part.toLowerCase()}`
})
}
方法流程说明:
dash
函数接受一个字符串 str
作为参数。replace
方法将大写字母前添加短横线并转换为小写。split
方法根据特殊字符分割字符串。map
方法将每个字符串转换为小写。parts
为空,则返回空字符串。parts
只有一个元素,则返回该元素。parts
有多个元素,使用 reduce
方法组合它们为短横线命名法的字符串。使用说明
str
转换为帕斯卡命名法(PascalCase),即每个单词的首字母大写,其余字母小写,且单词之间没有分隔符。如果输入字符串为空或长度为0,则返回空字符串。使用代码示例
import { pascal } from 'radash'
pascal('hello world') // => 'HelloWorld'
pascal('va va boom') // => 'VaVaBoom'
源码解析
// 定义一个名为 `pascal` 的函数。
export const pascal = (str: string): string => {
// 使用 `split` 方法根据点号、破折号、空格、下划线分割字符串,并将每个部分转换为小写。
const parts = str?.split(/[\.\-\s_]/).map(x => x.toLowerCase()) ?? []
// 如果处理后的字符串数组 `parts` 为空,则返回空字符串。
if (parts.length === 0) return ''
// 使用 `map` 方法将 `parts` 中的每个字符串的首字母大写。
// 使用 `charAt` 方法获取第一个字符并将其转换为大写,
// 然后将其与字符串的剩余部分(从第二个字符开始)连接起来。
// 使用 `join` 方法将这些首字母大写的字符串连接成一个单一的字符串。
return parts.map(str => str.charAt(0).toUpperCase() + str.slice(1)).join('')
}
方法流程说明:
pascal
函数接受一个字符串 str
作为参数。split
方法根据特殊字符分割字符串,并将每个字符串转换为小写。parts
为空,则返回空字符串。map
方法遍历 parts
数组,将每个字符串的首字母大写。join
方法将首字母大写的字符串数组连接成一个单一的字符串。使用说明
str
转换为蛇形命名法(snake_case)。这个函数接受一个字符串和一个可选的 options
对象作为参数,options
对象中的 splitOnNumber
属性用于指定是否在字母和紧随其后的数字之间添加下划线。使用代码示例
import { snake } from 'radash'
snake('green fish blue fish') // => green_fish_blue_fish
snake('5green fish 2blue fish') // => 5_green_fish_2_blue_fish
snake('5green fish 2blue fish', {
splitOnNumber: false
}) // => 5green_fish_2blue_fish
源码解析
// 定义一个名为 `snake` 的函数。
export const snake = (
// `str` 是要转换的字符串。
str: string,
// `options` 是一个可选的配置对象。
options?: {
// `splitOnNumber` 用于指定是否在字母和数字之间添加下划线。
splitOnNumber?: boolean
}
): string => {
// 使用 `replace` 和 `split` 方法处理输入字符串 `str`,并将每个部分转换为小写。
const parts =
str
// 使用 `replace` 方法将连续的大写字母转换为大写,并在每个大写字母前添加一个空格。
?.replace(/([A-Z])+/g, capitalize)
// 使用 `split` 方法根据大写字母或点号、破折号、空格、下划线分割字符串。
.split(/(?=[A-Z])|[\.\-\s_]/)
// 使用 `map` 方法将每个字符串转换为小写。
.map(x => x.toLowerCase()) ?? []
// 如果处理后的字符串数组 `parts` 为空,则返回空字符串。
if (parts.length === 0) return ''
// 如果 `parts` 只有一个元素,则返回该元素。
if (parts.length === 1) return parts[0]
// 使用 `reduce` 方法将 `parts` 中的字符串组合成蛇形命名法。
const result = parts.reduce((acc, part) => {
// 将当前字符串 `part` 转换为小写,并用下划线连接到累加器字符串 `acc`。
return `${acc}_${part.toLowerCase()}`
})
// 根据 `options` 中的 `splitOnNumber` 属性确定是否在字母和数字之间添加下划线。
return options?.splitOnNumber === false
? result
// 如果 `splitOnNumber` 不是 false,使用 `replace` 方法在字母和紧随其后的数字之间添加下划线。
: result.replace(/([A-Za-z]{1}[0-9]{1})/, val => `${val[0]!}_${val[1]!}`)
}
方法流程说明:
snake
函数接受一个字符串 str
和一个可选的配置对象 options
作为参数。replace
方法和 split
方法将字符串分割成小写的部分,并存储在 parts
数组中。parts
数组为空,则返回空字符串。parts
数组只有一个元素,则返回该元素。parts
数组有多个元素,使用 reduce
方法组合它们为蛇形命名法的字符串。options
对象中的 splitOnNumber
属性为 false
,则返回组合后的结果字符串 result
。options
对象中的 splitOnNumber
属性不是 false
或未指定,使用 replace
方法在字母和数字之间添加下划线。使用说明
data
替换字符串 str
中的模板占位符。函数接受三个参数:一个字符串 str
,一个数据对象 data
,以及一个可选的正则表达式 regex
用于匹配模板占位符。使用代码示例
import { template } from 'radash'
template('It is {{color}}', { color: 'blue' }) // => It is blue
template('It is <color>', { color: 'blue' }, /<(.+?)>/g) // => It is blue
源码解析
// 定义一个名为 `template` 的函数。
export const template = (
// `str` 是包含模板占位符的字符串。
str: string,
// `data` 是一个对象,包含要替换占位符的键值对。
data: Record<string, any>,
// `regex` 是一个可选的正则表达式,默认匹配双花括号内的内容。
regex = /\{\{(.+?)\}\}/g
) => {
// 使用 `matchAll` 方法和提供的正则表达式来匹配 `str` 中所有的模板占位符。
return Array.from(str.matchAll(regex)).reduce((acc, match) => {
// 在每次迭代中,使用 `replace` 方法将当前匹配的占位符 `match[0]`
// 替换为 `data` 对象中对应键 `match[1]` 的值。
return acc.replace(match[0], data[match[1]])
}, str) // 初始累加器是原始字符串 `str`。
}
方法流程说明:
template
函数接受一个字符串 str
,一个数据对象 data
,以及一个正则表达式 regex
作为参数。matchAll
方法和正则表达式 regex
来查找 str
中所有的模板占位符。reduce
方法遍历匹配结果数组。data
对象中获取对应的值并替换占位符。使用说明
str
转换为标题格式(Title Case),其中每个单词的首字母大写,其余字母小写,单词之间用空格分隔。如果输入字符串为空、null
或 undefined
,则返回空字符串。null
、undefined
)。使用代码示例
import { title } from 'radash'
title('hello world') // => 'Hello World'
title('va_va_boom') // => 'Va Va Boom'
title('root-hook') // => 'Root Hook'
title('queryItems') // => 'Query Items'
源码解析
// 定义一个名为 `title` 的函数。
export const title = (str: string | null | undefined): string => {
// 检查输入字符串是否为空、null 或 undefined,如果是,则返回空字符串。
if (!str) return ''
// 使用链式调用字符串方法来处理输入字符串 `str`。
return str
// 使用 `split` 方法根据大写字母或特殊字符(点号、破折号、空格、下划线)分割字符串。
.split(/(?=[A-Z])|[\.\-\s_]/)
// 使用 `map` 方法去除每个部分的前后空白字符。
.map(s => s.trim())
// 使用 `filter` 方法移除空字符串。
.filter(s => !!s)
// 使用 `map` 方法将每个部分转换为小写,并使用 `capitalize` 函数将首字母大写。
.map(s => capitalize(s.toLowerCase()))
// 使用 `join` 方法将处理后的字符串数组用空格连接成一个单一的字符串。
.join(' ')
}
方法流程说明:
title
函数接受一个可能为空、null
或 undefined
的字符串 str
作为参数。str
是空、null
或 undefined
,函数返回空字符串。split
方法将字符串分割成单词数组。map
方法去除单词的前后空白字符。filter
方法移除空字符串,确保只处理实际的单词。map
方法将每个单词转换为小写,并使用 capitalize
函数将单词的首字母大写。join
方法将单词数组连接成一个单一的字符串,单词之间用空格分隔。使用说明
null
或 undefined
,则返回空字符串。charsToTrim
参数指定了要去除的字符,默认为去除空格。使用代码示例
import { trim } from 'radash'
trim(' hello ') // => hello
trim('__hello__', '_') // => hello
trim('/repos/:owner/', '/') // => repos/:owner
源码解析
// 定义一个名为 `trim` 的函数。
export const trim = (
// `str` 是要处理的字符串,可以为空、null 或 undefined。
str: string | null | undefined,
// `charsToTrim` 是一个字符串,包含要从 `str` 的开头和结尾去除的字符,默认为去除空格。
charsToTrim: string = ' '
) => {
// 如果 `str` 为空、null 或 undefined,返回空字符串。
if (!str) return ''
// 使用 `replace` 方法将 `charsToTrim` 中的非字母数字字符转义,
// 以确保在创建正则表达式时将它们视为普通字符而非特殊字符。
const toTrim = charsToTrim.replace(/[\W]{1}/g, '\\$&')
// 创建一个正则表达式,用于匹配 `str` 开头和结尾的 `toTrim` 中的字符。
const regex = new RegExp(`^[${toTrim}]+|[${toTrim}]+$`, 'g')
// 使用 `replace` 方法和正则表达式 `regex` 从 `str` 的开头和结尾去除匹配的字符。
return str.replace(regex, '')
}
方法流程说明:
trim
函数接受一个字符串 str
和一个要去除的字符集 charsToTrim
作为参数。str
是空、null
或 undefined
,函数返回空字符串。charsToTrim
中的非字母数字字符被转义,以便在正则表达式中作为普通字符处理。new RegExp
创建一个正则表达式,它匹配 str
开头和结尾的 charsToTrim
中的字符。replace
方法将匹配的字符替换为空字符串,从而去除 str
开头和结尾的 charsToTrim
中的字符。我相信能看到最后的都是帅气多金又想进步的~~~~人才。
如果你想查看其他 radash
相关方法,前往主页查看
等所有方法更新完毕,作者会整理一份radash
完整方法目录上传,包括思维导图和使用目录。
大家有任何问题或见解,欢迎评论区留言交流和批评指正!!!
你的每一个收藏都是作者写作的动力!!!
目前为止,radash库的所有方法我们已经分享完毕。如果你想尝试使用,又或者想了解下源码,阿瓜的文章都值得一读,相信你总能有所收获。后续我们回整理一份使用说明进行发布。
或许你最近在某个地方听过或者看过 `radash` 这个词,它是一个typescript编写的方法库,无论你是想简单使用还是深入了解他的源码,本系列文章都值得一读。