学习《JavaScript高级程序设计》----day06


一、迭代器

1. 可迭代协议:

  • JavaScript中支持迭代的内置类型
    字符串、数组、Map、Set、arguments对象、NodeList等对象。

  • 接收可迭代对象的原生语言特性包括
    for-of数组解构、扩展操作符(...)、Array.from()、创建MapSetPromise.all()Promise.race()yield*操作符。

    // for-of
    const str = "string";
    for	(const char of str){
    	console.log(char);
    }
    
    // 数组解构
    const arr = ['foo', 'bar', 'baz'];
    const [a, b, c] = arr;
    console.log(a, b, c); // foo bar baz
    
    // 拓展操作符(...)
    const newArr = [...arr];
    console.log(newArr); // ['foo', 'bar', 'baz']
    
    // Array.from()
    const arr2 = Array.from([1, 2, 3, 4]);
    console.log(arr2); // [1, 2, 3, 4]
    
    //创建Map
    const set = new Set(arr);
    console.log(set);
    
    //创建Set
    const map = arr.map((x, i) => [i, x]);
    console.log(map);
    

2. 迭代器协议:

1.迭代器是一种一次性使用的对象,用于迭代与其关联的可迭代对象,使用next()在可迭代对象中遍历数据 。
2.迭代器维护着一个指向可迭代对象的引用,因此迭代器会阻止垃圾回收程序回收可迭代对象
3.迭代器并不与可迭代对象某个时刻的快照绑定,而仅仅是使用游标来记录遍历可迭代对象的历程。
自定义迭代器
主要是实现next()[Symbol.iterator]()方法, 实现return()方法用于迭代提前关闭时执行的逻辑。
自定义一次性计数迭代器

//自定义迭代器
class Counter {
    constructor(limit) {
        this.count = 1;
        this.limit = limit;
    }
    next() {
    	if (this.count <= this.limit) {
        	return {
            	value: this.count++,
                done: false
            };
        } else {
            return {
            	value: undefined,
                done: true
           };
       }
    }
    [Symbol.iterator]() {
    	return this;
    }
}
const counter = new Counter(10);
for (const i of counter) {
    console.log(i);// 打印 1 2 3 4 5 6 7 8 9 10
}
for (const i of counter) { //不可二次迭代
    console.log(i);// 不会打印
}

自定义重复性计数迭代器

class NewCounter {
    constructor(limit) {
            this.limit = limit;
        }
        [Symbol.iterator]() { //利用闭包实现多次迭代
            let count = 1,
                limit = this.limit;
            return {
                next() {
                    if (count <= limit) {
                        return {
                            value: count++,
                            done: false
                        };
                    } else {
                        return {
                            value: undefined,
                            done: true
                        };
                    }
                },
                return () {
                    console.log("iterator is exiting early");
                    return {
                        done: true,
                        value: undefined
                    };
                }
            }
        }
}
const newCounter = new NewCounter(10);
for (const el of newCounter) {
    console.log(el);
}
// 再次迭代
for (const el of newCounter) { 
    if (el > 5){ // 提前结束迭代器
     	break;
     }
    console.log(el);
}

二、生成器

1.概述:

1.生成器的形式就是一个函数,函数名称前加一个(*)表示它是一个生成器
2.生成器函数一开始处于暂停执行的状态,只会在初次调用next()方法后开始执行
3.生成器对象实现了Iterator接口,它们默认的迭代器是自引用

const myGenerator = function* (){
	console.log("打印日志");
}
const genertorObj = myGenerator();
console.log(genertorObj);
genertorObj.next();//打印日志

2.yield关键字:

1.yield关键字可以让生成器暂停和执行。
2.生成器函数在遇到yield关键字之前会正常执行代码,一旦遇到yield就会停止执行,函数作用域 的状态会被保留,想要再次执行,可以通过调用next()来恢复
3.一般来说,显示调用next()并不太方便,同时生成器对象可以当做可迭代对象,因此在开发中常常 将生成器对象当做可迭代对象来使用。
4.可以利用yield实现输入输出。
5.使用*增强yield的行为,让它能够迭代一个可迭代对象,从而一次产生一个值。
6.yield可以优雅地实现递归式。

function* generatorFn(){
	yield "boo";
	yield "bar";
	return "over";
}
const gObj = generatorFn();
console.log(gObj.next()); // { value: "boo", done: false }
console.log(gObj.next()); // { value: "bar", done: false }
console.log(gObj.next()); // { value: "over", done: true }
const obj = generatorFn();
for(const val of obj){
	console.log(val);
}

// 产生n个0
function* zeroes(n){
	while(n--){
		yield 0;
	}
}

//产生a到b之间的整数
function* range(a, b){
	while(b >= a){
		yield a++;
	}
}
console.log(Array.from(zeroes(10))); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
console.log(Array.from(range(1, 10))); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

function* fn(){
	yield* [1, 2, 3, 4];
}
for(const i of fn()){
	console.log(i); // 1 2 3 4
}

// 递归
function* nTimes(n){
	if(n > 0){
		yield* nTimes(n-1);
		yield n;
	}
}
for(const i of nTimes(10)){
	console.log(i); // 1 2 3 4 5 6 7 8 9 10
}

3.提前终止生成器:

实现return()方法用于迭代提前关闭时执行的逻辑,throw()也会使生成器提前关闭。

let nObj = nTimes(10);
try{//尝试提前关闭生成器对象
	nObj.throw("foo");
}catch(e){
	console.log(e);
}
console.log(nObj);
for(const i of nObj){//不会打印
	console.log(i);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值