ES6 Interator

摘要:
Interator“集合”数据的结构主要包括Array、Object、set和Map。任何数据结构都可以通过部署Iterator接口来完成遍历过程:创建指向当前数据结构起始位的指针。(遍历对象本质上是指针对象)。依次调用指针对象的下一个方法,指向数据结构成员直到结束。每次调用下一个方法时,都会返回对象当前成员的信息{value:text,done:true},其中值表示为

Interator

"集合"数据的结构主要有 ArrayObjectSet and Map ,任何数据结构只要部署 Iterator 接口,就可完成遍历操作

遍历过程:

  • 创建指针,指向当前数据结构起始位。(遍历对象本质是一个指针对象)。
  • 依次循环调用指针对象的 next方法,对应指向数据结构成员,直至结束。
    每次调用next方法,返回对象当前成员的信息{value:text,done:true},其中value 表示成员值,done` 表示遍历是否结束
let arr = ['Owen','18'];

let makeInterator = array =>{
    let  index = 0;
    return {
       next (){
        return index < array.length ? 
        {value:array[index++],done:false} : 
        {value:undefined, done:true}
        }
    }
}

let  inter = makeInterator(arr);
inter.next()
it.next() // { value: "Owen", done: false }
it.next() // { value: 18, done: false }
it.next() // { value: undefined, done: true }

对与遍历器对象来说 done: false and value:undefined 可省略

原生具备 Iterator 的数据结构:ArrayStringMapSetarguments and NodeList

都默认部署 [Symbol.iterator] 方法

//
const obj = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};
obj[Symbol.iterator]().next() //{value: 1, done: true}

let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();

iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
iter.next() // { value: undefined, done: true }

对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。


//原型上部署Interator
class RangeIterator {
  constructor(start, stop) {
    this.value = start;
    this.stop = stop;
  }

  [Symbol.iterator]() { return this; }

  next() {
    var value = this.value;
    if (value < this.stop) {
      this.value++;
      return {done: false, value: value};
    }
    return {done: true, value: undefined};
  }
}

function range(start, stop) {
  return new RangeIterator(start, stop);
}

for (var value of range(0, 3)) {
  console.log(value); // 0, 1, 2
}

//对象上部署Interator
function Obj(value) {
  this.value = value;
  this.next = null;
}

Obj.prototype[Symbol.iterator] = function() {
  var iterator = { next: next };

  var current = this;

  function next() {
    if (current) {
      var value = current.value;
      current = current.next;
      return { done: false, value: value };
    } else {
      return { done: true };
    }
  }
  return iterator;
}

var one = new Obj(1);
var two = new Obj(2);
var three = new Obj(3);

one.next = two;
two.next = three;

for (var i of one){
  console.log(i); // 1, 2, 3
}

类似数组对象,可引用 Array.prototype[Symbol.iterator]

//NodeList
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 或者
NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];

[...document.querySelectorAll('div')] 

//obj
let iterable = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
  console.log(item); // 'a', 'b', 'c'
}

一些 默认调用 Iterator 的操作


// 解构赋值
let set = new Set().add('a').add('b').add('c');

let [x,y] = set; // x='a'; y='b'

let [first, ...rest] = set; // first='a'; rest=['b','c'];

//扩展运算符

var str = 'hello';
[...str] //  ['h','e','l','l','o']

let arr = ['b', 'c'];
['a', ...arr, 'd']  // ['a', 'b', 'c', 'd']


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

let generator = function* () {
  yield 1;
  yield* [2,3,4];
  yield 5;
};

var iterator = generator();

iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }

// for...of
//for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、 Generator 对象,以及字符串。
let arr = document.querySelectorAll("p");

for (let item of arr ) {
    console.log(item)
}

/* 其他操作*/

Array.from()
Map(), Set(), WeakMap(), WeakSet() //生成对应数据结构
Promise.all()
Promise.race()

遍历器return方法和throw方法

return()

return方法必须返回一个对象。
如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return方法。
如果for...of循环提前退出(通常是因为出错,或者有break语句),就会调用return方法。

function readFile(file) {
    return {
        [Symbol.iterator]() {
            return {
                next() {
                    return {done:false}
                },
                return(){
                    file.close()
                    return {done:true}
                }
            };
        }
    };
}

//触发 return()
for (let line of readFile(fileName)) {
  console.log(line);
  break;
}
//触发 return()
for (let line of readLinesSync(fileName)) {
  console.log(line);
  throw new Error();
}

for...of 和其他遍历语法对比

let arr = [1,2];
//普通 `for`循环
 
for (var index = 0; index <arr.length; index++) {
  console.log(arr[index]);
}

/**
 * 书写比较麻烦
*/

// Array.forEach 

arr.forEach(function(item){
    console.log(item)
})

/**
 * 无法跳出循环,无法使用 break or return 
 */

// for...in

for (let index in arr) {
  console.log(arr[index]);
}

/**
 * 1.数组键名为字符串形式的数字
 * 2.会遍历出原型链上的键,和手动添加的键
 * 3.有些情况是无顺序遍历
 */

for (let item of arr) {
  console.log(item);
}

/**
 * 1.语法简洁
 * 2.没有 for...in 的缺点
 * 3.可以使用 return、break and continue
 * 
 */

免责声明:文章转载自《ES6 Interator》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇安全计算环境(三)Linux服务器2使用延迟的FileSystemWatcher来避免重复触发事件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

将excel中的数据转为json格式

---恢复内容开始--- 用来总结工作中碰导一些错误,可以让自己在碰到相同错误的时候不至于重新走一遍。。。。        昨天导入数据的时候,碰到了一个问题是将一个大数组里面的每一个元素中的一些不要的去提出掉,本身这些元素每一个本身也是数组,然后我去遍历大数组,又去遍历小数组,然后要赋值的条件就懵了,因为是双重循环,所以后面洗澡想起来可以用一个函数去跑内...

Opencv2系列学习笔记2(图像的遍历)

原文地址:http://blog.csdn.net/lu597203933/article/details/16359461 图像遍历主要有三种方法,本节主要介绍和比较这三种方法。 一:简单存取像素值        首先介绍一个名词—椒盐噪点:它是一种特殊的噪点,它随机的将图像中的部分像素设置为白色或者黑色。 Code: [cpp] view...

oracle start with connect by prior 递归查询用法

start with 子句:遍历起始条件,有个小技巧,如果要查父结点,这里可以用子结点的列,反之亦然。 connect by 子句:连接条件。关键词prior,prior跟父节点列parentid放在一起,就是往父结点方向遍历;prior跟子结点列subid放在一起,则往叶子结点方向遍历,                          parentid...

js forEach参数详解,forEach与for循环区别,forEach中如何删除数组元素

 壹 ❀ 引 在JS开发工作中,遍历数组的操作可谓十分常见了,那么像for循环,forEach此类方法自然也不会陌生,我个人也觉得forEach不值得写一篇博客记录,直到我遇到了一个有趣的问题,我们来看一段代码: let arr = [1, 2]; arr.forEach((item, index) => { arr.splice(inde...

ES6自我总结笔记(阮一峰ES6入门)

【let和const命令】 1.var的作用域是函数体内,不是块级作用域 2.let是更完美的var,let的变量的作用是块级作用域 3.let声明的全局变量不是全局对象属性,不可以通过window.变量名的方式访问 4.let声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在到达之前使用该变量会触发错误 5.用let重定义变量会抛出一个语法...

Dom4j总结

1、DOM4J简介 DOM4J是 dom4j.org 出品的一个开源 XML 解析包。DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。 DOM4J 使用起来非常简单。只要你了解基本的 XML-DOM 模型,就能使用。 Dom:把整个文档作为一个对象。 DOM4J 最大的特色是使用大量的接口。它的主要接口...