ES6中Iterator和for...of

1.Iterator 的遍历过程

说明:

  1. 遍历对象本质上就是一个指针对象。
  2. 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
  3. 第二次调用指针对象的next方法,可以将指针指向第二个成员。
  4. 依次进行。

2.默认Iterator接口

说明: Iterator接口的目的,就是为所有数据接口,提供了一种统一的访问机制,即for...of循环。一种数据结构只要部署了Iterator接口,我们称为这种数据结构时可遍历的。 ES6规定,默认的Iterator接口在数据结构Symbol.iterator属性,只要一个数据结构只要具有Symbol.iterator属性,就可以认为是可遍历的。

2.1例子

说明:Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数,执行这个函数,就会返回一个遍历器。

 const obj = {
            // 具有Symbol.iterator属性。
            [Symbol.iterator]: function () {
                // 返回一个遍历器对象。
                return {
                    // 对象的根本特征就是具有next方法。调用next方法就会返回成员的信息
                    next: function () {
                        return {
                            content: 1,
                            done: true,
                        };
                    },
                };
            },
        };
        console.log(obj[Symbol.iterator]().next()); //{content: 1, done: true}

2.2原生具有Iterator接口

说明:Array,Map,Set,String,NodeList对象,函数的arguments对象。

2.3数组

  let arr = ["张三", "李四", "王二"];
        let iterator = arr[Symbol.iterator]();
        console.log(iterator.next()); //{value: '张三', done: false}
        console.log(iterator.next()); //{value: '李四', done: false}
        console.log(iterator.next()); //{value: '王二', done: false}
        console.log(iterator.next()); //{value: undefined, done: true}

注意:上诉代码中,变量arr时一个数组,具有Iterator遍历器接口。对于原生部署Iterator接口的数据结构,不用自己写遍历器生成的函数,for...of循环会自动遍历他们。

2.4类似数组

说明:对于类似数组的对象(存在数值键名和length属性),部署Iterator接口,有一个简便方法,就是Symbol.iterator方法直接引用数组的Iterator接口。

  const obj1 = {
            0: "张三",
            1: "李四",
            2: "王二",
            length: 3,
            [Symbol.iterator]: Array.prototype[Symbol.iterator]
        };
        for (let i of obj1) {
            console.log(i);
            //张三
            // 李四
            // 王二
        }

注意:普通对象部署数组的Symbol.Iterator方法,并无效果。

3.调用Iterator接口情景

3.1.解构赋值

说明:数组和Set结构进行结构赋值时,会默认调用Symbol.iterator方法

  let set = new Set()
        set.add("李四").add("张三").add("王二")
        let [first, second] = set
        console.log(first); //李四
        console.log(second);//张三

3.2.扩展运算符

 const str = "GOOD"
        console.log(...str); //G O O D
        // 总结:任何部署了Iterator结构的数据的结构,都可以转成数组

3.3.yield*

说明:yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口

const generator = function* () {
            yield 1;
            yield* ["张三", "李四"]
            yield 5
        }
        const iterator1 = generator()
        console.log(iterator1.next());//{value: 1, done: false}
        console.log(iterator1.next());//{value: '张三', done: false}
        console.log(iterator1.next());//{value: '李四', done: false}
        console.log(iterator1.next());//{value: 5, done: false}
        console.log(iterator1.next());//{value: undefined, done: true}

3.4.字符串的Iterator接口

说明:字符串是一个类似数组的对象,也原生具有Iterator接口。

  let str1 = "FORE"
        console.log(typeof str1[Symbol.iterator]); //funcion
        // typeof可以检测除了null的基本数据结构,只能检测funtcion的引用数据类型
        const iterator2 = str1[Symbol.iterator]()
        console.log(iterator2.next()); //{value: 'F', done: false}
        console.log(iterator2.next());//{value: 'F', done: false}
        console.log(iterator2.next());//{value: 'R', done: false}
        console.log(iterator2.next());//{value: 'E', done: false}
        console.log(iterator2.next());//{value: undefined, done: true}

3.5.Iterator接口与Generaotor函数

 const iterator3 = {
            [Symbol.iterator]: function* () {
                yield 1
                yield 2
                yield 3
            }
        }
        console.log(...iterator3); //1 2 3
        //    简写形式
        const iterator4 = {
            *[Symbol.iterator]() {
                yield 1
                yield 2
            }
        }
        console.log(...iterator4); //1 2

3.6. 遍历器对象的return(),throw()

说明: 如果自己部署的话,那么return()和throw()是可选的,return主要对象在完成遍历时候,需要清理或释放资源,就可以部署return方法。

     let obj3 = {
            0: "张三",
            length: 1,
            [Symbol.iterator]: function () {
                return {
                    next: function () {
                        return {
                            content: "张三",
                            done: false
                        }
                    },

                }
            }
        }
        let iterator5 = obj3[Symbol.iterator]()
        console.log(iterator5.next()); //张三

3.7.for...of

说明:for...of作为遍历所有数据结构统一的方法,循环调用遍历器接口可以遍历Set和Map结构,某些类似数组的对象。

   const arr1 = ["张三", "李四", "王二"]
        for (let i of arr1) {
            console.log(i);
            //张三
            // 李四
            // 王二
        }

3.7.1.for...of替代了forEach()

  arr1.forEach((item, index, arr) => {
            console.log(item);
            console.log(index);
            console.log(arr);
        })

3.7.2.Js中原有的for...in循环

  const arr2 = ["张三", "李四", "王二"]
        for (let i in arr2) {
            console.log(i);
            // 0
            // 1
            // 2
        }

3.7.3.Set和Map结构

 const set1=new Set(["张三","李四","王二"])
        for(let i of set1){
            console.log(i);
            // 张三
            // 李四
            // 王二
        }
        const map1=new Map([["name","李四"],["age",18]])
        for(let i of map1){
            console.log(i);
            //  ['name', '李四']
            //  ['age', 18]
        }

3.7.4.类似数组的对象

    let str2="SPAY"
        for(let i of str2){
            console.log(i);
            //S
            //P
            //A
            //Y
        }
        function fun(){
            for(let i of arguments){
                console.log(i);
                // 1
                // 2
                // 3
            }
        }
        fun(1,2,3)

3.7.5对象

说明:只有部署了遍历器的函数的对象才可以用for...of遍历.

4.其他遍历语法的比较

说明:

  1. for函数过于复杂
  2. forEach()方法不能配合break,continue,return使用
  3.  for...in循环主要是为遍历对象而设计的,不适用于遍历数组。
  4. for...of循环相比上面几种做法,有一些显著的优点,不同于forEach方法,它可以与break、continue和return配合使用,提供了遍历所有数据结构的统一操作接口。

猜你喜欢

转载自blog.csdn.net/m0_62785037/article/details/130762653