使用Ts编写一个遍历数组和对象的方法
type Obj<T = any> = { [key in string | number]: T }
type Keys<T> = T extends (infer U)[] ? U : T[Extract<keyof T, string>]
type Callback<T extends Obj> = (item: T extends (infer U)[] ? U : T[Extract<keyof T, string>], index: number, source?: T) => any
type AsyncCallback<T extends Obj> = (item: T extends (infer U)[] ? U : T[Extract<keyof T, string>], index: number, source?: T) => Promise<any>
const isArray = (type: unknown): type is Array<any> => type instanceof Array
const isObject = (type: unknown): type is Obj => typeof type === 'object'
export const each = <T extends Obj> (source: T, fn: Callback<T>): void => {
if (isArray(source)) {
for (let i = 0, length = source.length; i < length; i++) {
if (fn(source[i], i, source) === true) return
}
} else if (isObject(source)) {
const keys = Reflect.ownKeys(source) as Array<keyof T>
for (let i = 0, length = keys.length; i < length; i++) {
const key = keys[i]
if (Reflect.has(source, key) && key !== 'constructor') {
if (fn(source[key], i, source) === true) return
}
}
} else {
fn(source, -1)
}
}
export const reverseEach = <T extends Obj> (source: T, fn: Callback<T>): void => {
if (isArray(source)) {
for (let i = source.length - 1; i >= 0; i--) {
if (fn(source[i], i, source) === true) return
}
} else if (isObject(source)) {
const keys = Reflect.ownKeys(source) as Array<keyof T>
for (let i = keys.length - 1; i >= 0; i--) {
const key = keys[i]
if (Reflect.has(source, key) && key !== 'constructor') {
if (fn(source[key], i, source) === true) return
}
}
} else {
fn(source, -1)
}
}
export const asyncEach = async <T extends Obj> (source: T, fn: AsyncCallback<T>): Promise<void> => {
if (isArray(source)) {
for (let i = 0; i < source.length; i++) {
const result = await fn(source[i], i, source)
if (result === true) return
}
} else if (isObject(source)) {
const keys = Reflect.ownKeys(source) as Array<keyof T>
for (let i = 0, length = keys.length; i < length; i++) {
const key = keys[i]
if (Reflect.has(source, key) && key !== 'constructor') {
const result = await fn(source[key], i, source)
if (result === true) return
}
}
} else {
await fn(source, -1)
}
}
使用
const list = [1, 2, 3]
each(list, (item, index) => {
if (item === 2) {
console.log(index)
return true
}
console.log('111')
})
const obj: { a: number, b: string, c: { d: number } } = { a: 12, b: '123', c: { d: 1234 } }
each(obj, (item, index) => {
if (typeof item === 'object') {
console.log(index, item.d)
return true
}
console.log('222')
})
![在这里插入图片描述](https://img-blog.csdnimg.cn/91903c53221940a197b7f229de4cf7d8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAY2hlbmRmXw==,size_20,color_FFFFFF,t_70,g_se,x_16)