• ES6-Iterator & for...of循环


    依赖文件地址 :https://github.com/chanceLe/ES6-Basic-Syntax/tree/master/js

      1 <!DOCTYPE html>
      2 <html>
      3     <head>
      4         <meta charset="UTF-8">
      5         <title>[es6]-13-Iterator和for...of循环</title>
      6         <script src="./js/browser.js"></script>
      7         <script type="text/babel">
      8             /*
      9              * Iterator遍历器的概念
     10              * 遍历器是一种接口,为各种不同的数据结构提供统一的访问机制。任何
     11              * 数据结构只要部署Iterator接口,就可以完成遍历操作。
     12              * 
     13              * Iterator的作用有三个:
     14              *  1.是为各种数据结构,提供一个统一的,简便的访问接口;
     15              *  2.使得数据结构的成员能够按某种次序排列。
     16              *  3.es6创造了新的遍历命令 for of 循环,Iterator接口主要供for...of消费。
     17              * 
     18              * 遍历的过程:
     19              *   1.创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
     20              *   2.第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
     21              *   3.第二次调用指针对象的next方法,可以将指针指向数据结构的第二个成员。
     22              *   4.不断调用指针对象的next方法,直到它指向数据结构的结束位置。
     23              * 
     24              * 每一次调用next方法,都会返回数据结构的当前成员信息。具体来说,就是返回一个包含value和done两个属性的对象。
     25              * 其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
     26              * 
     27              * 下面是一个模拟next方法返回值的例子:
     28              */
     29             
     30             
     31             var makeIterator = (array)=>{
     32                 var nextIndex = 0;
     33                 return {
     34                     next:function(){
     35                             return nextIndex < array.length?
     36                             {value:array[nextIndex++],done:false}:
     37                             {value:undefined,done:true }
     38                         
     39                     }
     40                 }
     41             };
     42             var it = makeIterator(["a","b"]);
     43             console.log(it.next());
     44             console.log(it.next());
     45             console.log(it.next());
     46             
     47             /*
     48              * Object {value: "a", done: false}
     49                Object {value: "b", done: false}
     50                Object {value: undefined, done: true}
     51              */
     52             
     53             /*
     54              * es6中,有些数据结构原生具备Iterator接口,比如数组,不用任何处理就可以被for...of循环,有些就不行
     55              * 比如对象,原因在于这些数据结构原生部署了Symbol.iterator属性。另外一些数据结构没有。凡是部署了
     56              * Symbol.iterator属性的数据结构,就叫部署了遍历器接口,调用这个接口,就会返回一个遍历器对象。
     57              */
     58             
     59             /*
     60              * 数据结构的默认iterator接口
     61              * ES6规定,默认的iterator接口部署在数据结构的Symbol.iterator属性,Symbol.iterator本身是一个表达式,返回Symbol对象的
     62              * iterator属性,这是一个预定义好的,类型为Symbol的特殊值,所以放在方括号内。
     63              * 
     64              * ES6 中,有三类数据原生具备iterator接口:数组,某些类似数组的对象,Set和Map结构。
     65              * 
     66              * 对象之所以没有默认部署iterator接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。
     67              * 本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。    不过严格的说,对象
     68              * 部署遍历器接口并不是很必要,因为这时对象实际是被当做Map来使用,ES5没有Map结构,ES6原生提供了。
     69              * 
     70              * 一个对象要有可被for...of循环调用的iterator接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
     71              * 
     72              * 调用iterator接口的场合:
     73              * 1.解构赋值2.扩展运算符。3.yield* 后面跟的是一个可遍历结构,会调用该结构的遍历器接口。4.其他场合。
     74              */
     75             
     76             /*
     77              * 字符串的iterator接口
     78              * 字符串是一个类似数组的对象,也原生具有iterator接口。
     79              * 可以通过重写Symbol.iterator属性,达到修改遍历器行为的目的。
     80              */
     81             
     82             /*
     83              * 遍历器对象的return() throw()
     84              * 遍历器对象除了具有next方法,还可以具有return和throw方法。如果自己写遍历器对象生成函数,next方法是必须部署的,return方法和throw方法可选。
     85              * return 方法的使用场合是,如果for...of循环提前退出(通常是因为出错或者有break语句或continue语句),就会调用return方法。
     86              * 如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return方法。
     87              */
     88             function readLinesSync(file){
     89                 return {
     90                     next(){
     91                         if(file.isAtEndOfFile()){
     92                             file.close();
     93                             return {done:true};
     94                         }
     95                     },
     96                     return(){
     97                         file.close();
     98                         return {done:true};
     99                     }
    100                 }
    101             }
    102             /*
    103              * 上面代码中,函数readLinesSync接受一个文件对象作为参数,返回一个遍历器对象,其中除了next方法,还部署了return方法。
    104              * 下面我们让文件的遍历提前返回,这样就会触发执行return的方法。
    105              */
    106             for(let line of readLinesSync(filename)){
    107                 console.log(line);
    108                 break;
    109             }
    110             //注意return方法必须返回一个对象,这是Generator规格决定的。
    111             
    112             /*
    113              * throw方法主要是配合Generator函数使用,一般的遍历器对象用不到这个方法。
    114              */
    115             
    116             /*
    117              * for...of循环 , 只要有遍历器接口,就可以被for...of循环。
    118              * 使用范围包括 :  数组,Set和Map结构,某些类似数组的对象(比如arguments,DOMList对象)  Generator  以及字符串。
    119              * 
    120              * 与其他遍历语法的比较:
    121              * 最原始的是for循环,这种写法比较麻烦,因此数组提供内置的forEach方法。
    122              * 
    123              * forEach的问题在于,无法中途跳出循环,break或return 都没作用。
    124              * 
    125              * for...in  遍历数组的键名,有几个缺点:
    126              *    数组的键名是数字,但是for...in是以字符串作为键名。
    127              *    不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
    128              *    某些情况下,for...in循环会以任意顺序遍历键名。
    129              * 
    130              * 总之,for...in循环主要是为遍历对象设计的,不适合数组。
    131              * 
    132              * for...of循环相比上面几种做法,有显著优点:
    133              *   1.有着for...in一样简洁的语法,没有for...in的缺点。
    134              *   2.可以与break,return 结合使用。
    135              *   3.提供了遍历所有数据结构的统一操作接口。
    136              * 
    137              */
    138             
    139             
    140         </script>
    141     </head>
    142     <body>
    143     </body>
    144 </html>
  • 相关阅读:
    51nod1376 最长递增子序列的数量
    51nod1201 整数划分
    51nod1202 子序列个数
    51nod 博弈论水题
    51nod1052 最大M子段和
    51nod1678 lyk与gcd
    51nod1262 扔球
    BZOJ2763, 最短路
    吃西瓜 最大子矩阵 三维的。 rqnoj93
    noip2015 信息传递 强连通块
  • 原文地址:https://www.cnblogs.com/chengyunshen/p/7191671.html
Copyright © 2020-2023  润新知