arrify 转数组
源码实现:
- 判断传来参数的类型
- 根据不同类型实现不同转换
- Symbol.iterator方法数组类型都有此方法,这个属性对象是没有的。
export default function arrify(value) {
if (value === null || value === undefined) {
return [];
}
if (Array.isArray(value)) {
return value;
}
if (typeof value === 'string') {
return [value];
}
if (typeof value[Symbol.iterator] === 'function') {
return [...value];
}
return [value];
}
迭代器
迭代器:从一个数据集合中按照一定的顺序,不断取出数据的过程。
迭代器应该具有得到下一个数据的能力;迭代器应该具有判断是否还有后续数据的能力。
迭代器的遍历过程:
- 创建一个指针对象,指向当前数据结构的起始位置,迭代器对象本质是一个指针对象
// 这里的arr可以是Array、Map、Set、String、类数组(伪数组)、NodeList对象、函数arguments等类型
let it: Iterator<number> = arr[Symbol.iterator]()
- 第一次调用指针对象的next方法,将指针指向了数据结构的第一个成员
// 通过此方法将指针指向第一个成员
it.next();
// 输出结果:{ value: 值, done: 布尔值 }
// value表示值,done表示是否不能迭代了,true表示后面没有值了,已经结束了
- 第二次调用指针对象的next方法,将指针指向了数据结构的第二个成员
- 不断调用,以此类推,直到它指向了数据结构的结束位置
生成器
生成器:ES6中新增的一种函数控制、使用的方案,它可以让我们更加灵活的控制函数什么时候继续执行、暂停执行等。
生成器是一个函数,与普通函数区别:
- 生成器函数需要在function的后面加一个符号:
*
- 生成器函数可以通过
yield
关键字来控制函数的执行流程 - 生成器函数的返回值是一个
Generator(生成器)
// 1.定义了一个生成器函数
function* foo() {
yield "cccccc" // 返回数据格式为{ value: 'xxx', done: boolean }
console.log("d")
console.log("e")
yield
console.log("f")
console.log("g")
}
// 2.调用生成器函数, 会返回一个生成器对象
const generator = foo()
// 当遇到yield时 会执行到与yield右边的代码后中断 yield左边如果有代码不执行 例如上面第一个yield后面还有代码也会执行
// generator.next()输出结果为yield后面的值
conosle.log(generator.next())// 输出:{ value: 'cccccc', done: false }
generator.next()// d e
generator.next()// f g
生成器提前结束:generator.return()
return后这个生成器函数就会结束,之后调用next不会继续生成值了
生成器抛出异常:generator.throw()
抛出异常后我们可以在生成器函数中捕获异常
使用生成器写一个迭代器:
function* Generator (arr) {
// 方法一:使用yield*来生产一个可迭代对象
// yield* arr;
// 方法二:
for (let i = 0; i < arr.length; i++) {
yield arr[i];
}
}
const names = ['a', 'b', 'c'];
const generator = Generator(names);
console.log(generator.next()); // { value: 'a', done: false }
console.log(generator.next()); // { value: 'b', done: false }
console.log(generator.next()); // { value: 'c', done: false }
console.log(generator.next()); // { value: undefined, done: true }
index.d.ts
声明文件
export default function arrify<ValueType>(
value: ValueType
): ValueType extends (null | undefined)
? [] // eslint-disable-line @typescript-eslint/ban-types
: ValueType extends string
? [string]
: ValueType extends readonly unknown[]
? ValueType
: ValueType extends Iterable<infer T>
? T[]
: [ValueType];
// ValueType 是泛型变量 extends用于泛型约束
ValueType extends (null | undefined) ? [] : ValueType extends string // ValueType extends (null | undefined) 为false执行 ValueType extends string
ValueType extends string ? [string] : ValueType extends readonly unknown[] // ValueType extends string 为false执行 ValueType extends readonly unknown[]
ValueType extends readonly unknown[]? ValueType : ValueType extends Iterable<infer T> // ValueType extends readonly unknown[] 为false执行 ValueType extends Iterable<infer T>
// Iterable<infer T> 表示的是某种可遍历类型,里面的每一项具体类型不知,以T推断,如果ValueType符合这种情况,那么返回值为包含各种T的数组
ValueType extends Iterable<infer T>? T[] : [ValueType] // ValueType extends Iterable<infer T> 为false执行 [ValueType]