1.什么是生成器

生成器就是通过构造函数Generator创建出来的对象,生成器即是一个迭代器,同时又是一个可迭代的对象

创建生成器

只需要把函数变成Generator函数

```javascript
function* test(){

	}
	const generator = test();  //next  symbol
	console.log(generator) // 迭代器
### 生成的内部执行
// 关键字  yield  只能在函数内部使用,表示产生一个迭代数据
// 每一次调用生成器的next方法,会将生成器函数运行到下一个yield关键字位置

		```javascript
function *test(){
			console.log(123);
		}
		const generator = test();  //生成了一个生成器而已
		generator.next()

斐波拉契生成器

// 创建一个斐波那契数列的迭代器
		function *createFeiboIterator(){
			let prev1 = 1;
			let prev2 = 1;  //定义前两位
			let n = 1;  //当前第几位
			while(true){
				if(n <= 2){
					yield 1
				}else{
					const newValue = prev1 + prev2;
					yield newValue;
					prev2 = prev1
					prev1 = newValue;
				}
				n++;
			}
		}
		const iterator = createFeiboIterator()
			// 注意的点:
		// 1.生成器有返回值,出现在最后一次的done为true的value中
		// 2.调用生成的next方法时,可以传递参数,传递的参数会交给yield表达式的返回值
		// 3.第一次去调用函数的时候,传递的参数是没有任何含义的
		function *test(){
			let info = yield 1;
			console.log(info)
			info = yield 2 + info;
			console.log(info)
		}
		const generator = test();
其他API

1.return方法 调用以后,可以提前结束生成器函数,整个的迭代过程提前结束

function *test(){
			yield 1;
			yield 2;
			yield 3;
			return 4;
		}

// 2.throw 可以在生成器产生一个错误,抛出到对应的行
const generator = test();

在函数内调用其他生成器

// 在函数内部是调用别的生成器
		function *fun1(){
			yield "a";
			yield "b";
		}
		function* fun2(){
			// fun1()
			// yield fun1()
			yield *fun1()   //在生成器函数内部去调用别的生成器函数,一定要加上*
			yield 1;
			yield 2;
			yield 3;
		} 
		const generator = fun2();
		console.log(generator)

set集合

array object 在不同的场景去发挥作用的

// set用于存放不重复的数据
		const s1 = new Set(iterable);
		console.log(s1)
		const s1 = new Set([1,2,3,4,5,6,7,8,9,1,23,4,5,6])
		console.log(s1)
// 会转换成字符串对象,再进行存储
		const s1 = new Set("lasdkjflksdjflksdjf");
		console.log(s1)
		console.log(new String("sadfsdf"))
// 原型方法(实例方法)
		// add()
		const s1 = new Set();
		s1.add(1)
		s1.add(2)
		s1.add(3)
		s1.add(1)   //无效的
		console.log(s1)
		// Object.is()   +0 和 -0 set是认为相等的
		s1.add(+0);
		s1.add(-0);
		console.log(s1)
		// has()
		console.log(s1.has(1))
		console.log(s1.has(10))

		// delete()  返回是否删除成功
		console.log(s1.delete(1))
		console.log(s1.delete(10))

		// clear()  
		// s1.clear()
		console.log(s1)

		// size属性  只能读,不能改
		// console.log(s1.size)

		// 遍历
		// for of
		for(const item of s1){
			console.log(item)
		}
		// 重写的实例方法  forEach
		s1.forEach((item,index,s) => {
			// index 不是下标,set集合没有下标
			// forEach中的第一个参数的值和第二个参数的值是相同的,都表示set中的每一项

			console.log(item,index,s)
		})

map集合

map集合
map键值对,特点:键名不能重复

对象存储的问题
	1.键名只能是字符串
	2.获取数据的数量的时候不方便
	3.键名容易和原型上的名称发生冲突
//创建
		const map = new Map(iterable);
	    //传递的应该为二维数组,数组的子数组里面只能有两项,第一项为键,第二项为值
		console.log(map)
const map = new Map([
				["a",123],
				["b",456],
				["c",789],
				["d",1]
			])
		console.log(map)

		// 后续操作
		// size
		console.log(map.size)

		// set() 传递的是键值对,两个参数,键是可以为任意类型的
		map.set("e","alsdjk")
		const obj = {};  //看引用值
		map.set(obj,1111)
		map.set(obj,1122)
		console.log(map)   //map长度是多少?
		// 键不存在,则添加一项
		// 键存在,则修改

		// get()
		console.log(map.get("a"))
		console.log(map.get({}))  //what?

		// has()

		// delete()

		// clear()

		// 遍历
		// for(const item of map){
		// 	console.log(item[0],item[1])
		// }
		// for(const [key,value] of map){   //解构
		// 	console.log(key,value)
		// }

		map.forEach((value,key,map) => {
			console.log(value,key,map)
			value 值
			key 键
			map 对象本身
		})