assign:递归合并两个对象
使用说明
使用代码示例
import { assign } from 'radash'
const ra = {
name: 'Ra',
power: 100
}
assign(ra, { name: 'Loki' })
// => { name: Loki, power: 100 }
复制代码
源码解析
// 定义一个泛型函数 `assign`。
export const assign = <X extends Record<string | symbol | number, any>>(
// `initial` 是初始对象,它的属性可能被 `override` 对象中的属性覆盖。
initial: X,
// `override` 是覆盖对象,其属性将覆盖或添加到 `initial` 对象中。
override: X
): X => {
// 如果 `initial` 或 `override` 为空,则返回非空的那个,或者如果都为空则返回一个空对象。
if (!initial || !override) return initial ?? override ?? {}
// 使用 `Object.entries` 和 `reduce` 方法合并 `initial` 和 `override` 对象。
return Object.entries({ ...initial, ...override }).reduce(
(acc, [key, value]) => {
// 在每次迭代中,构建累加器 `acc`,它是最终返回的新对象。
return {
...acc,
[key]: (() => {
// 如果 `initial` 中的对应属性是一个对象,则递归地调用 `assign` 进行合并。
if (isObject(initial[key])) return assign(initial[key], value)
// 如果属性值是数组,这里有一个注释掉的代码行,似乎是未完成的逻辑。
// if (isArray(value)) return value.map(x => assign)
// 对于非对象属性,直接使用 `override` 中的值。
return value
})()
}
},
{} as X // 初始累加器是一个类型为 `X` 的空对象。
)
}
复制代码
方法流程说明:
assign
函数接受两个参数,initial
和 override
,它们都是对象。
如果其中一个对象为空,函数将返回另一个非空对象。
如果两个对象都为空,函数返回一个空对象。如果两个对象都非空,函数使用 Object.entries
和 reduce
方法遍历 override
对象的所有属性。
对于每个属性,如果 initial
对象中对应的属性也是一个对象,则递归地调用 assign
函数来合并这两个对象。
如果 initial
对象中对应的属性不是对象,或 override
对象中的属性在 initial
对象中不存在,则直接使用 override
对象中的值。
返回合并后的新对象。
clone:浅拷贝对象
使用说明
使用代码示例
import { clone } from 'radash'
const ra = {
name: 'Ra',
power: 100
}
const gods = [ra]
clone(ra) // => copy of ra
clone(gods) // => copy of gods
复制代码
源码解析
// 定义一个泛型函数 `clone`。
export const clone = <T>(obj: T): T => {
// 如果 `obj` 是原始值(如数字、字符串或布尔值),则不需要克隆,直接返回 `obj`。
if (isPrimitive(obj)) {
return obj
}
// 如果 `obj` 是一个函数,则通过 `bind` 方法创建一个新的绑定函数,
// 并将其绑定到一个空对象上,以创建一个函数的副本。
if (typeof obj === 'function') {
return obj.bind({})
}
// 获取 `obj` 的构造函数,并使用 `new` 操作符创建一个新的对象实例。
// 这个方法同样适用于创建数组的副本。
const newObj = new ((obj as object).constructor as { new (): T })()
// 遍历 `obj` 的所有自有属性,并将它们复制到新对象 `newObj` 中。
Object.getOwnPropertyNames(obj).forEach(prop => {
// 这里使用了类型断言 `(newObj as any)` 和 `(obj as any)` 来绕过类型检查,
// 因为函数开头已经检查了原始值的情况。
;(newObj as any)[prop] = (obj as any)[prop]
})
// 返回新创建的对象 `newObj`。
return newObj
}
复制代码
方法流程说明:
如果 obj
是一个原始值,直接返回它,因为原始值在 JavaScript 中是不可变的。
如果 obj
是一个函数,使用 bind
方法创建并返回一个新的函数副本。
如果 obj
是一个对象或数组,使用 obj
的构造函数创建一个新的空对象或空数组 newObj
。
遍历 obj
的自有属性,并将每个属性值复制到 newObj
中。
返回新对象 newObj
。
construct:把扁平对象构建为深层对象(多维)
使用说明
使用代码示例
import { construct } from 'radash'
const flat = {
name: 'ra',
power: 100,
'friend.name': 'loki',
'friend.power': 80,
'enemies.0.name': 'hathor',
'enemies.0.power': 12
}
construct(flat)
// {
// name: 'ra',
// power: 100,
// friend: {
// name: 'loki',
// power: 80
// },
// enemies: [
// {
// name: 'hathor',
// power: 12
// }
// ]
// }
复制代码
源码解析
// 定义一个泛型函数 `construct`。
export const construct = <TObject extends object>(obj: TObject): object => {
// 如果 `obj` 为空,则直接返回一个新的空对象。
if (!obj) return {}
// 使用 `Object.keys` 获取 `obj` 的所有自有属性的键名,
// 然后使用 `reduce` 方法来构建新对象。
return Object.keys(obj).reduce((acc, path) => {
// 对每个属性键名 `path`,调用 `set` 函数来设置新对象 `acc` 的属性。
// `(obj as any)[path]` 获取 `obj` 中对应属性的值。
// `set` 函数的具体实现未提供,我们可以假设它正确地设置了 `acc` 的属性。
return set(acc, path, (obj as any)[path])
}, {}) // 初始累加器 `acc` 是一个空对象。
}
复制代码
方法流程说明:
construct
函数接受一个对象 obj
作为参数。
如果 obj
为空,函数返回一个空对象。
如果 obj
非空,函数遍历 obj
的所有自有属性。
对于每个属性,函数使用 set
函数将 obj
中的属性值复制到新对象中。
返回构建完成的新对象。
crush:把深层(多维)对象构建成扁平对象(construct 的相反操作)
使用说明
使用代码示例
import { crush } from 'radash'
const ra = {
name: 'ra',
power: 100,
friend: {
name: 'loki',
power: 80
},
enemies: [
{
name: 'hathor',
power: 12
}
]
}
crush(ra)
// {
// name: 'ra',
// power: 100,
// 'friend.name': 'loki',
// 'friend.power': 80,
// 'enemies.0.name': 'hathor',
// 'enemies.0.power': 12
// }
复制代码
源码解析
// 定义一个泛型函数 `crush`。
export const crush = <TValue extends object>(value: TValue): object => {
// 如果 `value` 为空,则直接返回一个空对象。
if (!value) return {}
// 使用 `objectify` 函数来构建新对象。
// `objectify` 函数的具体实现未提供,我们可以假设它以某种方式构建对象。
return objectify(
// 使用 `keys` 函数获取 `value` 的所有键名。
// `keys` 函数的具体实现未提供,我们可以假设它返回对象的所有键名。
keys(value),
// 使用标识函数 `k => k` 作为键生成函数,意味着新对象的键将与原始对象的键相同。
k => k,
// 使用 `get` 函数获取 `value` 对象中每个键对应的值。
// `get` 函数的具体实现未提供,我们可以假设它正确地获取了对象中的属性值。
k => get(value, k)
)
}
复制代码
方法流程说明:
crush
函数接受一个对象 value
作为参数。
如果 value
为空,函数返回一个空对象。
如果 value
非空,函数使用 keys
函数获取 value
的所有键名。
函数调用 objectify
,传入键名数组、键生成函数(这里是标识函数 k => k
)和值生成函数(通过调用 get(value, k)
获取每个键的值)。
objectify
函数返回一个新对象,这个对象的属性和值与 value
相同。
get:获取对象中的任意属性,可以通过 .
的方式获取深层的属性
使用说明
使用代码示例
import { get } from 'radash'
const fish = {
name: 'Bass',
weight: 8,
sizes: [
{
maturity: 'adult',
range: [7, 18],
unit: 'inches'
}
]
}
get( fish, 'sizes[0].range[1]' ) // 18
get( fish, 'sizes.0.range.1' ) // 18
get( fish, 'foo', 'default' ) // 'default'
复制代码
源码解析
// 定义一个泛型函数 `get`。
export const get = <TDefault = unknown>(
// 第一个参数 `value` 是一个任意类型的值,它是要访问属性的对象。
value: any,
// 第二个参数 `path` 是一个字符串,表示对象属性的路径,使用点或方括号表示法。
path: string,
// 第三个可选参数 `defaultValue` 是一个默认值,如果无法访问路径,则返回此值。
defaultValue?: TDefault
): TDefault => {
// 使用正则表达式分割路径字符串,得到一个属性名的数组 `segments`。
const segments = path.split(/[.[]]/g)
// 初始化一个变量 `current`,用于遍历属性路径。
let current: any = value
// 遍历 `segments` 中的每个属性名 `key`。
for (const key of segments) {
// 如果 `current` 是 `null` 或 `undefined`,则返回 `defaultValue`。
if (current === null || current === undefined) return defaultValue as TDefault
// 移除属性名中的引号。
const dequoted = key.replace(/['"]/g, '')
// 如果属性名为空(可能是由于路径字符串中的多余点或方括号),则跳过此迭代。
if (dequoted.trim() === '') continue
// 将 `current` 更新为当前属性名 `dequoted` 对应的值。
current = current[dequoted]
}
// 如果最终的 `current` 是 `undefined`,则返回 `defaultValue`。
if (current === undefined) return defaultValue as TDefault
// 否则,返回找到的值。
return current
}
复制代码
方法流程说明:
get
函数接受一个对象 value
,一个表示属性路径的字符串 path
,以及一个可选的默认值 defaultValue
。
使用正则表达式分割 path
字符串,得到一个表示属性链的数组 segments
。遍历 segments
数组,依次访问每个属性。
如果在访问过程中遇到 null
或 undefined
,或者到达路径的末尾但找不到值,则返回 defaultValue
。
如果成功访问到路径上的所有属性,并找到了值,则返回这个值。
invert:把对象中的key
和value
对调
使用说明
使用代码示例
import { invert } from 'radash'
const powersByGod = {
ra: 'sun',
loki: 'tricks',
zeus: 'lighning'
}
invert(gods) // => { sun: ra, tricks: loki, lightning: zeus }
复制代码
源码解析
// 定义一个泛型函数 `invert`。
export const invert = <
// 泛型 `TKey` 表示对象的键的类型。
TKey extends string | number | symbol,
// 泛型 `TValue` 表示对象的值的类型。
TValue extends string | number | symbol
>(
// 参数 `obj` 是一个对象,其键的类型为 `TKey`,值的类型为 `TValue`。
obj: Record<TKey, TValue>
): Record<TValue, TKey> => {
// 如果 `obj` 为空,则返回一个空对象。
if (!obj) return {} as Record<TValue, TKey>
// 使用 `Object.keys` 获取 `obj` 的所有键,并断言键的类型为 `TKey`。
const keys = Object.keys(obj) as TKey[]
// 使用 `reduce` 方法遍历所有键,创建一个新对象,其键为 `obj` 的值,值为 `obj` 的键。
return keys.reduce((acc, key) => {
// 将 `obj` 的值 `obj[key]` 作为新对象 `acc` 的键,原始键 `key` 作为新对象的值。
acc[obj[key]] = key
// 返回累加器 `acc`,它是正在构建的反转对象。
return acc
}, {} as Record<TValue, TKey>) // 初始累加器是一个空对象,类型为 `Record<TValue, TKey>`。
}
复制代码
keys:获取对象中所有的key
,包括深层的(表示成 a.b 的形式)
使用说明
使用代码示例
import { keys } from 'radash'
const ra = {
name: 'ra',
power: 100,
friend: {
name: 'loki',
power: 80
},
enemies: [
{
name: 'hathor',
power: 12
}
]
}
keys(ra)
// => [
// 'name',
// 'power',
// 'friend.name',
// 'friend.power',
// 'enemies.0.name',
// 'enemies.0.power'
// ]
复制代码
源码解析
// 定义一个泛型函数 `keys`。
export const keys = <TValue extends object>(value: TValue): string[] => {
// 如果 `value` 为空,则返回一个空数组。
if (!value) return []
// 定义一个递归函数 `getKeys`,用于遍历嵌套对象或数组并获取所有键的路径。
const getKeys = (nested: any, paths: string[]): string[] => {
// 如果当前值 `nested` 是一个对象,递归地遍历它的每一个键值对。
if (isObject(nested)) {
return Object.entries(nested).flatMap(([k, v]) =>
// 对于每一个键值对,将键 `k` 添加到路径数组 `paths` 中,
// 并继续递归地遍历值 `v`。
getKeys(v, [...paths, k])
)
}
// 如果当前值 `nested` 是一个数组,递归地遍历它的每一个元素。
if (isArray(nested)) {
return nested.flatMap((item, i) =>
// 对于每一个元素,将索引 `i` 转换为字符串并添加到路径数组 `paths` 中,
// 然后继续递归地遍历元素 `item`。
getKeys(item, [...paths, `${i}`])
)
}
// 如果当前值 `nested` 既不是对象也不是数组,说明已经到达叶子节点,
// 将路径数组 `paths` 连接成字符串并返回。
return [paths.join('.')]
}
// 使用 `getKeys` 函数从根开始遍历 `value`,并获取所有键的路径。
return getKeys(value, [])
}
复制代码
方法流程说明:
keys
函数接受一个对象 value
作为参数。
如果 value
为空,函数返回一个空数组。
如果 value
非空,函数定义了一个递归辅助函数 getKeys
。getKeys
函数递归地遍历嵌套对象或数组,收集所有键的路径。
对于嵌套对象,getKeys
遍历每个键值对,并对值递归调用自身。
对于嵌套数组,getKeys
遍历每个元素,并对元素递归调用自身,使用元素索引作为路径的一部分。
当到达叶子节点(即不再是对象或数组)时,getKeys
将收集到的路径数组 paths
连接成字符串并返回。
keys
函数返回一个包含所有属性键路径的数组。
listify:把对象的键值对转换成一个由特定结构元素组成的数组
使用说明
使用代码示例
import { listify } from 'radash'
const fish = {
marlin: {
weight: 105,
},
bass: {
weight: 8,
}
}
listify(fish, (key, value) => ({ ...value, name: key })) // => [{ name: 'marlin', weight: 105 }, { name: 'bass', weight: 8 }]
复制代码
源码解析
// 定义一个泛型函数 `listify`。
export const listify = <TValue, TKey extends string | number | symbol, KResult>(
// 参数 `obj` 是一个对象,其键的类型为 `TKey`,值的类型为 `TValue`。
obj: Record<TKey, TValue>,
// 参数 `toItem` 是一个函数,它接受一个键和一个值,并返回一个新的结果类型 `KResult` 的元素。
toItem: (key: TKey, value: TValue) => KResult
) => {
// 如果 `obj` 为空,则返回一个空数组。
if (!obj) return []
// 使用 `Object.entries` 获取 `obj` 的所有键值对。
const entries = Object.entries(obj)
// 如果 `obj` 没有键值对,返回一个空数组。
if (entries.length === 0) return []
// 使用 `reduce` 方法遍历所有键值对,构建结果数组。
return entries.reduce((acc, entry) => {
// 对每个键值对,调用 `toItem` 函数,并将返回的元素添加到累加器数组 `acc` 中。
acc.push(toItem(entry[0] as TKey, entry[1] as TValue))
// 返回累加器 `acc`。
return acc
}, [] as KResult[]) // 初始累加器是一个空数组,其元素类型为 `KResult`。
}
复制代码
方法流程说明:
listify
函数接受一个对象 obj
和一个转换函数 toItem
作为参数。
如果 obj
为空,函数返回一个空数组。
如果 obj
非空,函数使用 Object.entries
获取 obj
的所有键值对。
如果 obj
没有键值对,函数返回一个空数组。
如果 obj
有键值对,函数使用 reduce
方法遍历键值对数组。
对于每个键值对,函数调用 toItem
函数,传入键和值,并将返回的新元素添加到累加器数组中。
返回构建完成的结果数组。
lowerize:将对象的所有key
转换为小写形式
使用说明
使用代码示例
import { lowerize } from 'radash'
const ra = {
Mode: 'god',
Power: 'sun'
}
lowerize(ra) // => { mode, power }
复制代码
源码解析
// 定义一个泛型函数 `lowerize`。
export const lowerize = <T extends Record<string, any>>(obj: T) =>
// 调用 `mapKeys` 函数将 `obj` 的所有键转换为小写。
mapKeys(obj, k => k.toLowerCase()) as LowercasedKeys<T>
// `LowercasedKeys<T>` 是一个类型,表示将 `T` 的键转换为小写后的新类型。
// 定义一个泛型函数 `mapKeys`。
export const mapKeys = <
// `TValue` 表示对象的值的类型。
TValue,
// `TKey` 表示对象原始键的类型。
TKey extends string | number | symbol,
// `TNewKey` 表示映射后的新键的类型。
TNewKey extends string | number | symbol
>(
// `obj` 是一个对象,其键的类型为 `TKey`,值的类型为 `TValue`。
obj: Record<TKey, TValue>,
// `mapFunc` 是一个映射函数,它接受一个键和一个值,并返回一个新的键。
mapFunc: (key: TKey, value: TValue) => TNewKey
): Record<TNewKey, TValue> => {
// 使用 `Object.keys` 获取 `obj` 的所有键,并断言键的类型为 `TKey`。
const keys = Object.keys(obj) as TKey[]
// 使用 `reduce` 方法遍历所有键,创建一个新对象,其键为 `mapFunc` 函数的返回值,值为 `obj` 的值。
return keys.reduce((acc, key) => {
// 调用 `mapFunc` 函数获取新键,并将 `obj` 中的值赋给新键。
acc[mapFunc(key as TKey, obj[key])] = obj[key]
// 返回累加器 `acc`,它是正在构建的新对象。
return acc
}, {} as Record<TNewKey, TValue>) // 初始累加器是一个空对象,类型为 `Record<TNewKey, TValue>`。
}
复制代码
方法流程说明:
lowerize
函数接受一个对象 obj
作为参数。
它调用 mapKeys
函数,传入 obj
和一个将键转换为小写的函数。
mapKeys
函数遍历 obj
的所有键,并将每个键转换为小写。
mapKeys
返回一个新对象,这个对象的键是小写形式,值与原始对象 obj
相同。
lowerize
函数返回这个新对象,并使用 LowercasedKeys<T>
类型断言来指明返回值的类型。
upperize:将对象的所有key
转换为大写形式
使用说明
使用代码示例
import { upperize } from 'radash'
const ra = {
Mode: 'god',
Power: 'sun'
}
upperize(ra) // => { MODE, POWER }
复制代码
源码解析
// 定义一个泛型函数 `upperize`。
export const upperize = <T extends Record<string, any>>(obj: T) =>
// 调用 `mapKeys` 函数将 `obj` 的所有键转换为大写。
mapKeys(obj, k => k.toUpperCase()) as UppercasedKeys<T>
// `UppercasedKeys<T>` 是一个类型,表示将 `T` 的键转换为大写后的新类型。
// 定义一个泛型函数 `mapKeys`。
export const mapKeys = <
// `TValue` 表示对象的值的类型。
TValue,
// `TKey` 表示原始对象的键的类型。
TKey extends string | number | symbol,
// `TNewKey` 表示映射后的新键的类型。
TNewKey extends string | number | symbol
>(
// `obj` 是一个对象,其键的类型为 `TKey`,值的类型为 `TValue`。
obj: Record<TKey, TValue>,
// `mapFunc` 是一个映射函数,它接受一个键和一个值,并返回一个新的键。
mapFunc: (key: TKey, value: TValue) => TNewKey
): Record<TNewKey, TValue> => {
// 使用 `Object.keys` 获取 `obj` 的所有键,并断言它们的类型为 `TKey`。
const keys = Object.keys(obj) as TKey[]
// 使用 `reduce` 方法遍历所有键,创建一个新对象,其键为 `mapFunc` 函数的返回值,值为 `obj` 的值。
return keys.reduce((acc, key) => {
// 调用 `mapFunc` 函数获取新键,并将 `obj` 中的值赋给新键。
acc[mapFunc(key as TKey, obj[key])] = obj[key]
// 返回累加器 `acc`,它是正在构建的新对象。
return acc
}, {} as Record<TNewKey, TValue>) // 初始累加器是一个空对象,类型为 `Record<TNewKey, TValue>`。
}
复制代码
方法流程说明:
upperize
函数接受一个对象 obj
作为参数。
它调用 mapKeys
函数,传入 obj
和一个将键转换为大写的函数。
mapKeys
函数遍历 obj
的所有键,并将每个键转换为大写。
mapKeys
返回一个新对象,这个对象的键是大写形式,值与原始对象 obj
相同。
upperize
函数返回这个新对象,并使用 UppercasedKeys<T>
类型断言来指明返回值的类型。
mapEntries:将对象的键值对通过一个转换函数映射为新的对象
使用说明
使用代码示例
import { mapEntries } from 'radash'
const ra = {
name: 'Ra',
power: 'sun',
rank: 100,
culture: 'egypt'
}
mapEntries(ra, (key, value) => [key.toUpperCase(), `${value}`]) // => { NAME: 'Ra', POWER: 'sun', RANK: '100', CULTURE: 'egypt' }
复制代码
源码解析
// 定义一个泛型函数 `mapEntries`。
export const mapEntries = <
// `TKey` 表示原始对象的键的类型。
TKey extends string | number | symbol,
// `TValue` 表示原始对象的值的类型。
TValue,
// `TNewKey` 表示新对象的键的类型。
TNewKey extends string | number | symbol,
// `TNewValue` 表示新对象的值的类型。
TNewValue
>(
// `obj` 是一个对象,其键的类型为 `TKey`,值的类型为 `TValue`。
obj: Record<TKey, TValue>,
// `toEntry` 是一个转换函数,它接受一个键和一个值,并返回一个新的键值对的元组。
toEntry: (key: TKey, value: TValue) => [TNewKey, TNewValue]
): Record<TNewKey, TNewValue> => {
// 如果 `obj` 为空,则返回一个空对象。
if (!obj) return {} as Record<TNewKey, TNewValue>
// 使用 `Object.entries` 获取 `obj` 的所有键值对,并使用 `reduce` 方法来构建新对象。
return Object.entries(obj).reduce((acc, [key, value]) => {
// 对每个键值对,调用 `toEntry` 函数,并获取新键 `newKey` 和新值 `newValue`。
const [newKey, newValue] = toEntry(key as TKey, value as TValue)
// 将新键值对添加到累加器对象 `acc` 中。
acc[newKey] = newValue
// 返回累加器 `acc`。
return acc
}, {} as Record<TNewKey, TNewValue>) // 初始累加器是一个空对象,类型为 `Record<TNewKey, TNewValue>`。
}
复制代码
方法流程说明:
mapEntries
函数接受一个对象 obj
和一个转换函数 toEntry
作为参数。
如果 obj
为空,函数返回一个空对象。
如果 obj
非空,函数使用 Object.entries
获取 obj
的所有键值对。
函数使用 reduce
方法遍历键值对数组。
对于每个键值对,函数调用 toEntry
函数,传入键和值,并将返回的新键值对添加到累加器数组中。
返回构建完成的结果对象。
mapKeys:把对象的kye
通过一个映射函数转换为新的key
使用说明
使用代码示例
import { mapKeys } from 'radash'
const ra = {
mode: 'god',
power: 'sun'
}
mapKeys(ra, key => key.toUpperCase()) // => { MODE, POWER }
mapKeys(ra, (key, value) => value) // => { god: 'god', power: 'power' }
复制代码
源码解析
// 定义一个泛型函数 `mapKeys`。
export const mapKeys = <
// `TValue` 表示对象的值的类型。
TValue,
// `TKey` 表示原始对象的键的类型。
TKey extends string | number | symbol,
// `TNewKey` 表示映射后的新键的类型。
TNewKey extends string | number | symbol
>(
// `obj` 是一个对象,其键的类型为 `TKey`,值的类型为 `TValue`。
obj: Record<TKey, TValue>,
// `mapFunc` 是一个映射函数,它接受一个键和一个值,并返回一个新的键。
mapFunc: (key: TKey, value: TValue) => TNewKey
): Record<TNewKey, TValue> => {
// 使用 `Object.keys` 获取 `obj` 的所有键,并断言它们的类型为 `TKey`。
const keys = Object.keys(obj) as TKey[]
// 使用 `reduce` 方法遍历所有键,创建一个新对象,其键为 `mapFunc` 函数的返回值,值为 `obj` 的值。
return keys.reduce((acc, key) => {
// 调用 `mapFunc` 函数获取新键,并将 `obj` 中的值赋给新键。
acc[mapFunc(key as TKey, obj[key])] = obj[key]
// 返回累加器 `acc`,它是正在构建的新对象。
return acc
}, {} as Record<TNewKey, TValue>) // 初始累加器是一个空对象,类型为 `Record<TNewKey, TValue>`。
}
复制代码
方法流程说明:
mapKeys
函数接受一个对象 obj
和一个映射函数 mapFunc
作为参数。
函数使用 Object.keys
获取 obj
的所有键。
函数使用 reduce
方法遍历键数组。
对于每个键,函数调用 mapFunc
函数,传入键和值,并将返回的新键作为新对象的键。
新对象的值与原始对象 obj
中的值相同。
返回构建完成的新对象。
mapValues:对象的value
通过一个映射函数转换为新的value
使用说明
使用代码示例
import { clone } from 'radash'
const ra = {
name: 'Ra',
power: 100
}
const gods = [ra]
clone(ra) // => copy of ra
clone(gods) // => copy of gods
复制代码
源码解析
// 定义一个泛型函数 `mapValues`。
export const mapValues = <
// `TValue` 表示原始对象的值的类型。
TValue,
// `TKey` 表示对象键的类型。
TKey extends string | number | symbol,
// `TNewValue` 表示映射后的新值的类型。
TNewValue
>(
// `obj` 是一个对象,其键的类型为 `TKey`,值的类型为 `TValue`。
obj: Record<TKey, TValue>,
// `mapFunc` 是一个映射函数,它接受一个值和一个键,并返回一个新的值。
mapFunc: (value: TValue, key: TKey) => TNewValue
): Record<TKey, TNewValue> => {
// 使用 `Object.keys` 获取 `obj` 的所有键,并断言它们的类型为 `TKey`。
const keys = Object.keys(obj) as TKey[]
// 使用 `reduce` 方法遍历所有键,创建一个新对象,其键与 `obj` 相同,值为 `mapFunc` 函数的返回值。
return keys.reduce((acc, key) => {
// 调用 `mapFunc` 函数获取新值,并将其赋给新对象 `acc` 的同名键。
acc[key] = mapFunc(obj[key], key)
// 返回累加器 `acc`,它是正在构建的新对象。
return acc
}, {} as Record<TKey, TNewValue>) // 初始累加器是一个空对象,类型为 `Record<TKey, TNewValue>`。
}
复制代码
方法流程说明:
mapValues
函数接受一个对象 obj
和一个映射函数 mapFunc
作为参数。
函数使用 Object.keys
获取 obj
的所有键。
函数使用 reduce
方法遍历键数组。
对于每个键,函数调用 mapFunc
函数,传入值和键,并将返回的新值作为新对象的值。
新对象的键与原始对象 obj
中的键相同。
返回构建完成的新对象。
omit:创建一个省略了 keys
数组中指定的一些键的新对象
使用说明
使用代码示例
import { omit } from 'radash'
const fish = {
name: 'Bass',
weight: 8,
source: 'lake',
brackish: false
}
omit(fish, ['name', 'source']) // => { weight, brackish }
复制代码
源码解析
// 定义一个泛型函数 `omit`。
export const omit = <T, TKeys extends keyof T>(
// `obj` 是一个对象,其类型为泛型 `T`。
obj: T,
// `keys` 是一个数组,包含对象 `obj` 中要省略的键名,键名的类型为 `TKeys`。
keys: TKeys[]
): Omit<T, TKeys> => {
// 如果 `obj` 为空,则返回一个空对象。
if (!obj) return {} as Omit<T, TKeys>
// 如果 `keys` 为空或长度为0,则返回原始对象 `obj`。
if (!keys || keys.length === 0) return obj as Omit<T, TKeys>
// 使用 `reduce` 方法遍历 `keys` 数组,从 `obj` 中省略指定的键。
return keys.reduce(
(acc, key) => {
// 在这个较为局限的上下文中,允许直接在累加器对象 `acc` 上使用 `delete` 操作符。
// 这是出于性能考虑,通常不建议在其他地方使用这种模式。
delete acc[key]
// 返回更新后的累加器 `acc`。
return acc
},
// 使用对象展开运算符 `{ ...obj }` 创建 `obj` 的浅拷贝,以避免直接修改原始对象。
{ ...obj }
)
}
复制代码
方法流程说明:
omit
函数接受一个对象 obj
和一个键名数组 keys
作为参数。
如果 obj
为空,函数返回一个空对象。
如果 keys
为空或长度为 0,函数返回原始对象 obj
。
如果 keys
非空,函数使用 reduce
方法遍历 keys
数组。
对于每个键名 key
,函数使用 delete
操作符将其从累加器对象 acc
中删除。
函数返回省略了指定键的新对象。
pick:创建一个只包含原始对象中指定的 keys`的对象
使用说明
使用代码示例
import { pick } from 'radash'
const fish = {
name: 'Bass',
weight: 8,
source: 'lake',
barckish: false
}
pick(fish, ['name', 'source']) // => { name, source }
复制代码
源码解析
// 定义一个泛型函数 `pick`。
export const pick = <T extends object, TKeys extends keyof T>(
// `obj` 是一个对象,其类型为泛型 `T`。
obj: T,
// `keys` 是一个数组,包含对象 `obj` 中要选择的键名,键名的类型为 `TKeys`。
keys: TKeys[]
): Pick<T, TKeys> => {
// 如果 `obj` 为空,则返回一个空对象。
if (!obj) return {} as Pick<T, TKeys>
// 使用 `reduce` 方法遍历 `keys` 数组,从 `obj` 中选择指定的键。
return keys.reduce((acc, key) => {
// 检查 `obj` 是否自身拥有属性 `key`(不是从原型链继承来的)。
if (Object.prototype.hasOwnProperty.call(obj, key))
// 如果 `obj` 拥有 `key`,则将其添加到累加器对象 `acc` 中。
acc[key] = obj[key]
// 返回累加器 `acc`。
return acc
}, {} as Pick<T, TKeys>) // 初始累加器是一个空对象,类型为 `Pick<T, TKeys>`。
}
复制代码
方法流程说明:
pick
函数接受一个对象 obj
和一个键名数组 keys
作为参数。
如果 obj
为空,函数返回一个空对象。
如果 obj
非空,函数使用 reduce
方法遍历 keys
数组。
对于每个键名 key
,函数检查 obj
是否自身拥有这个属性(而不是从原型链继承的)。
如果 obj
自身拥有这个属性,函数将这个属性及其值添加到累加器对象 acc
中。
函数返回包含所选键的新对象。
set:在一个对象中设置一个由点或方括号表示法指定的路径上的值
使用说明
功能说明:用于在一个对象中设置一个值,该值位于由点或方括号表示法指定的路径上。如果路径中的任何中间对象不存在,set
函数将创建它们。
参数:初始对象、属性路径字符串、设置值。
使用代码示例
import { set } from 'radash'
set({}, 'name', 'ra')
// => { name: 'ra' }
set({}, 'cards[0].value', 2)
// => { cards: [{ value: 2 }] }
复制代码
源码解析
// 定义一个泛型函数 `set`。
export const set = <T extends object, K>(
// `initial` 是初始对象,我们将在其中设置值。
initial: T,
// `path` 是一个字符串,表示要设置值的属性路径。
path: string,
// `value` 是我们要设置在路径上的值。
value: K
): T => {
// 如果 `initial` 为空,则返回一个空对象。
if (!initial) return {} as T
// 如果 `path` 为空或 `value` 未定义,则返回原始对象 `initial`。
if (!path || value === undefined) return initial
// 使用正则表达式分割路径字符串,得到一个属性名的数组 `segments`。
// 过滤掉空字符串,确保所有段都是有效的。
const segments = path.split(/[.[]]/g).filter(x => !!x.trim())
// 定义一个递归辅助函数 `_set`。
const _set = (node: any) => {
// 如果路径 `segments` 有多个段,我们需要深入嵌套结构。
if (segments.length > 1) {
// 弹出当前段的键名 `key`。
const key = segments.shift() as string
// 检查下一个段是否表示数组索引。
const nextIsNum = toInt(segments[0], null) === null ? false : true
// 如果当前键不存在,创建一个新的对象或数组,取决于下一个段是否是数字。
node[key] = node[key] === undefined ? (nextIsNum ? [] : {}) : node[key]
// 递归调用 `_set` 函数,继续设置值。
_set(node[key])
} else {
// 如果路径 `segments` 只有一个段,直接在当前节点上设置值。
node[segments[0]] = value
}
}
// ...(函数的其余部分)
}
复制代码
方法流程说明:
set
函数接受一个对象 initial
,一个路径字符串 path
,和一个值 value
作为参数。
如果 initial
为空,函数返回一个空对象。
如果 path
为空或 value
未定义,函数返回原始对象 initial
。
函数使用正则表达式分割 path
字符串,得到一个表示属性链的数组 segments
。
函数定义了一个递归辅助函数 _set
,它负责沿着 segments
的路径设置值。
如果 segments
数组有多个元素,函数递归地创建或获取中间对象,并继续沿着路径设置值。
如果 segments
数组只有一个元素,函数在当前的节点上设置值。
_set
函数从根对象 initial
开始递归设置值。
shake:过滤对象
使用说明
使用代码示例
import { shake } from 'radash'
const ra = {
mode: 'god',
greek: false,
limit: undefined
}
shake(ra) // => { mode, greek }
shake(ra, a => !a) // => { mode }
复制代码
源码解析
// 定义一个泛型函数 `shake`。
export const shake = <RemovedKeys extends string, T>(
// 参数 `obj` 是一个对象,其类型为泛型 `T`。
obj: T,
// 参数 `filter` 是一个可选的函数,用于决定哪些属性应该被省略。
// 默认情况下,它会过滤掉值为 `undefined` 的属性。
filter: (value: any) => boolean = x => x === undefined
): Omit<T, RemovedKeys> => {
// 如果 `obj` 为空,则返回一个空对象。
// 这里返回的类型应该是 `Omit<T, RemovedKeys>` 而不是 `T`。
if (!obj) return {} as Omit<T, RemovedKeys>
// 使用 `Object.keys` 获取 `obj` 的所有键,并将其类型断言为 `T` 的键的类型数组。
const keys = Object.keys(obj) as (keyof T)[]
// 使用 `reduce` 方法遍历所有键,创建一个新对象。
return keys.reduce((acc, key) => {
// 如果 `filter` 函数对当前键的值返回 `true`,则省略该属性。
if (filter(obj[key])) {
return acc
} else {
// 否则,将属性添加到累加器对象 `acc` 中。
acc[key] = obj[key]
return acc
}
}, {} as Omit<T, RemovedKeys>) // 初始累加器是一个空对象,类型为 `Omit<T, RemovedKeys>`。
}
复制代码
方法流程说明:
shake
函数接受一个对象 obj
和一个可选的过滤函数 filter
作为参数。
如果 obj
为空,函数返回一个空对象。
如果 obj
非空,函数使用 Object.keys
获取 obj
的所有键。
函数使用 reduce
方法遍历键数组。
对于每个键,函数使用 filter
函数检查对应的值,以确定是否应该省略该属性。
如果 filter
函数返回 false
,函数将该属性及其值添加到累加器对象 acc
中。
返回包含所选属性的新对象。
文章转载自:雾散声声慢
原文链接:https://www.cnblogs.com/muqiqiang/p/18211285
体验地址:http://www.jnpfsoft.com/?from=infoq
评论