源码解读二:arrify

arrify 转数组

源码实现:

  1. 判断传来参数的类型
  2. 根据不同类型实现不同转换
  3. 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];
}

迭代器

迭代器:从一个数据集合中按照一定的顺序,不断取出数据的过程。
迭代器应该具有得到下一个数据的能力;迭代器应该具有判断是否还有后续数据的能力。
迭代器的遍历过程:

  1. 创建一个指针对象,指向当前数据结构的起始位置,迭代器对象本质是一个指针对象
// 这里的arr可以是Array、Map、Set、String、类数组(伪数组)、NodeList对象、函数arguments等类型
let it: Iterator<number> = arr[Symbol.iterator]()
  1. 第一次调用指针对象的next方法,将指针指向了数据结构的第一个成员
// 通过此方法将指针指向第一个成员
it.next();
// 输出结果:{ value: 值, done: 布尔值 }
// value表示值,done表示是否不能迭代了,true表示后面没有值了,已经结束了
  1. 第二次调用指针对象的next方法,将指针指向了数据结构的第二个成员
  2. 不断调用,以此类推,直到它指向了数据结构的结束位置

生成器

生成器:ES6中新增的一种函数控制、使用的方案,它可以让我们更加灵活的控制函数什么时候继续执行、暂停执行等。
生成器是一个函数,与普通函数区别:

  1. 生成器函数需要在function的后面加一个符号:*
  2. 生成器函数可以通过yield关键字来控制函数的执行流程
  3. 生成器函数的返回值是一个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]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hoki802

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值