es陆 语法 (iterator和for…of循环)

Iterator遍历器

遍历器(Iterator)便是如此一种体制。它是一种接口,为种种分歧的数据结构提供统一的走访机制。任何数据结构只要计划Iterator接口,就足以成功遍历操作(即依次拍卖该数据结构的装有成员)。

作用:

  • 为各个数据结构,提供八个联结的、简便的访问接口
  • 使得数据结构的分子能够按某种次序排列
  • ES6创设了一种新的遍历命令for...of巡回,Iterator接口首要供for...of消费

Iterator的遍历进度:

(一)创设2个指针对象,指向当前数据结构的开端地点。也正是说,遍历器对象本质上,就是贰个指针对象。

(二)第贰遍调用指针对象的next措施,能够将指针指向数据结构的率先个成员。

(三)首回调用指针对象的next主意,指针就本着数据结构的第叁个分子。

(四)不断调用指针对象的next办法,直到它指向数据结构的甘休地点。

在ES陆中,有3类数据结构原生具有Iterator接口:数组、有个别类似数组的对象、Set和Map结构。

能够覆盖原生的Symbol.iterator艺术,到达修改遍历器行为的目的。

Iterator和for…of循环

  1. Iterator(遍历器)的概念
  2. 数据结构的暗中同意Iterator接口
  3. 调用Iterator接口的场面
  4. 字符串的Iterator接口
  5. Iterator接口与Generator函数
  6. 遍历器对象的return(),throw()%EF%BC%8Cthrow())
  7. for…of循环

Iterator(遍历器)的概念

JavaScript原有的代表“集合”的数据结构,主借使数组(Array)和对象(Object),ES陆又增多了Map和Set。那样就有了三种多少会集,用户还足以构成使用它们,定义本身的数据结构,比方数组的成员是Map,Map的分子是目的。那样就须要一种统一的接口机制,来拍卖全部分化的数据结构。

遍历器(Iterator)就是那样一种机制。它是一种接口,为各样区别的数据结构提供统1的造访机制。任何数据结构只要陈设Iterator接口,就足以做到遍历操作(即依次拍卖该数据结构的具有成员)。

Iterator的功能有四个:1是为各种数据结构,提供1个统壹的、简便的拜访接口;贰是驱动数据结构的分子能够按某种次序排列;3是ES陆成立了一种新的遍历命令for...of巡回,Iterator接口重要供for...of消费。

Iterator的遍历进度是如此的。

(一)创制1个指南针对象,指向当前数据结构的伊始地点。也正是说,遍历器对象本质上,正是贰个指南针对象。

(二)第二遍调用指针对象的next格局,能够将指针指向数据结构的首先个成员。

(三)第二回调用指针对象的next方式,指针就本着数据结构的第二个成员。

(四)不断调用指针对象的next艺术,直到它指向数据结构的收尾地方。

每一遍调用next主意,都会回到数据结构的当下成员的消息。具体来讲,正是重返1个饱含valuedone两日本性的对象。个中,value品质是日前成员的值,done性能是3个布尔值,表示遍历是还是不是得了。

下边是一个效仿next措施再次来到值的事例。

var it = makeIterator(['a', 'b']);

it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

地点代码定义了三个makeIterator函数,它是二个遍历器生成函数,效用正是再次回到叁个遍历器对象。对数组['a', 'b']es陆 语法 (iterator和for…of循环)。奉行那些函数,就能回到该数组的遍历器对象(即指针对象)it

指南针对象的next艺术,用来移动指针。最先时,指针指向数组的起先地方。然后,每一遍调用next主意,指针就能够指向数组的下3个成员。第二次调用,指向a;第壹次调用,指向b

next办法再次回到1个目标,表示近来多少成员的音信。那个目的具有valuedone两性子格,value性情再次来到当前岗位的分子,done脾气是二个布尔值,表示遍历是不是停止,就是不是还有须要再3回调用next方法。

简单来说,调用指针对象的next主意,就足以遍历事先给定的数据结构。

对此遍历器对象的话,done: falsevalue: undefined属性都是足以省略的,由此地方的makeIterator函数能够简写成下边包车型地铁款型。

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++]} :
        {done: true};
    }
  };
}

出于Iterator只是把接口规范加到数据结构之上,所以,遍历器与它所遍历的十分数据结构,实际上是分其他,完全能够写出从未对号入座数据结构的遍历器对象,或然说用遍历器对象模拟出数据结构。上边是3个然则运营的遍历器对象的事例。

var it = idMaker();

it.next().value // '0'
it.next().value // '1'
it.next().value // '2'
// ...

function idMaker() {
  var index = 0;

  return {
    next: function() {
      return {value: index++, done: false};
    }
  };
}

地点的事例中,遍历器生成函数idMaker,重返几个遍历器对象(即指针对象)。可是并不曾对应的数据结构,恐怕说,遍历器对象本身讲述了3个数据结构出来。

在ES6中,某个数据结构原生具备Iterator接口(比如数组),即不用其余处理,就能够被for...of巡回遍历,有个别就可怜(比如对象)。原因在于,那些数据结构原生布署了Symbol.iterator质量(详见下文),此外一些数据结构未有。凡是安排了Symbol.iterator本性的数据结构,就叫做陈设了遍历器接口。调用这一个接口,就能够回到八个遍历器对象。

假设运用TypeScript的写法,遍历器接口(Iterable)、指针对象(Iterator)和next方法重回值的尺度能够描述如下。

interface Iterable {
  [Symbol.iterator]() : Iterator,
}

interface Iterator {
  next(value?: any) : IterationResult,
}

interface IterationResult {
  value: any,
  done: boolean,
}

for…of

for…of循环能够运用的限量包蕴数组、Set和Map结构、某个类似数组的靶子(比方arguments对象、DOM
NodeList对象)、后文的Generator对象,以及字符串。

 

{
  let arr=['hello','world'];
  let map=arr[Symbol.iterator]();
  //done表示是否还有下一步了,false有 true 没有
  console.log(map.next()); //{value: "hello", done: false}
  console.log(map.next()); //{value: "world", done: false}
  console.log(map.next()); //{value: undefined, done: true}
}

{
  let obj={
    start:[1,3,2],
    end:[7,9,8],
    //声明
    [Symbol.iterator](){
      //函数体
      let self=this;
      let index=0; //当前遍历索引
      let arr=self.start.concat(self.end); //合并数组
      let len=arr.length;//记住数组长度
      return {
        //iterator部署的时候一定要有next这个方法
        next(){
          //遍历过程
          if(index<len){
            return {
              value:arr[index++],
              done:false
            }
          }else{
            return {
              value:arr[index++],
              done:true //遍历结束
            }
          }
        }
      }
    }
  }
  //验证接口是否部署成功
  for(let key of obj){
    console.log('key1',key); //1 3 2 7 9 8
  }
}

{
  let arr=['hello','world'];
  for(let value of arr){
    console.log('value',value); //hello ,world
  }
}

 

 

Iterator(遍历器)的概念

JavaScript原有的意味“集合”的数据结构,首如果数组(Array)和目的(Object),ES6又增加了Map和Set。那样就有了两种多少集合,用户仍可以够组成使用它们,定义本人的数据结构,例如数组的成员是Map,Map的成员是目标。那样就供给一种统壹的接口机制,来拍卖全部分歧的数据结构。

遍历器(Iterator)正是如此一种体制。它是1种接口,为各类区别的数据结构提供统一的访问机制。任何数据结构只要安排Iterator接口,就足以成功遍历操作(即依次拍卖该数据结构的具有成员)。

Iterator的成效有八个:壹是为种种数据结构,提供多少个联合的、简便的造访接口;二是驱动数据结构的分子能够按某种次序排列;三是ES六创造了1种新的遍历命令for...of巡回,Iterator接口首要供for...of消费。

Iterator的遍历进度是那般的。

(一)创立叁个指针对象,指向当前数据结构的开局地方。也便是说,遍历器对象本质上,便是一个指南针对象。

(二)第一遍调用指针对象的next方法,能够将指针指向数据结构的率先个分子。

(叁)第三遍调用指针对象的next方法,指针就针对数据结构的第3个分子。

(4)不断调用指针对象的next方式,直到它指向数据结构的终结位置。

每二遍调用next艺术,都会回去数据结构的脚下成员的音信。具体来说,就是回到多个分包valuedone八个属性的靶子。在那之中,value属性是时下成员的值,done脾气是二个布尔值,表示遍历是不是终止。

上边是三个效仿next艺术再次回到值的例子。

var it = makeIterator(['a', 'b']);

it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

上边代码定义了2个makeIterator函数,它是八个遍历器生成函数,功用便是回到2个遍历器对象。对数组['a', 'b']实践那些函数,就能回到该数组的遍历器对象(即指针对象)it

指南针对象的next格局,用来移动指针。发轫时,指针指向数组的始发地点。然后,每一次调用next措施,指针就能够指向数组的下一个成员。第3回调用,指向a;第2遍调用,指向b

next措施再次来到1个目的,表示近来多少成员的音信。那些目的具备valuedone五个属性,value质量再次来到当前地方的成员,done质量是三个布尔值,表示遍历是还是不是甘休,便是不是还有供给再度调用next方法。

简单的说,调用指针对象的next方法,就可以遍历事先给定的数据结构。

对此遍历器对象的话,done: falsevalue: undefined品质都以足以总结的,因而地点的makeIterator函数能够简写成下边包车型地铁样式。

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++]} :
        {done: true};
    }
  };
}

由于Iterator只是把接口规范加到数据结构之上,所以,遍历器与它所遍历的不得了数据结构,实际上是分开的,完全能够写出从未相应数据结构的遍历器对象,大概说用遍历器对象模拟出数据结构。上边是贰个最为运维的遍历器对象的例证。

var it = idMaker();

it.next().value // '0'
it.next().value // '1'
it.next().value // '2'
// ...

function idMaker() {
  var index = 0;

  return {
    next: function() {
      return {value: index++, done: false};
    }
  };
}

地方的例子中,遍历器生成函数idMaker,重返3个遍历器对象(即指针对象)。不过并未相应的数据结构,或然说,遍历器对象本人讲述了2个数据结构出来。

在ES陆中,有个别数据结构原生具备Iterator接口(举例数组),即不用此外管理,就能够被for...of巡回遍历,有些就老大(比如对象)。原因在于,那几个数据结构原生铺排了Symbol.iterator属性(详见下文),其余一些数据结构未有。凡是计划了Symbol.iterator质量的数据结构,就叫做计划了遍历器接口。调用这些接口,就能够回到1个遍历器对象。

只要运用TypeScript的写法,遍历器接口(Iterable)、指针对象(Iterator)和next方法重回值的口径能够描述如下。

interface Iterable {
  [Symbol.iterator]() : Iterator,
}

interface Iterator {
  next(value?: any) : IterationResult,
}

interface IterationResult {
  value: any,
  done: boolean,
}

数据结构的默许Iterator接口

Iterator接口的目标,就是为全数数据结构,提供了1种统1的拜会机制,即for...of巡回(详见下文)。当使用for...of循环遍历某种数据结构时,该循环会自动去搜寻Iterator接口。

一种数据结构只要安插了Iterator接口,大家就称那种数据结构是”可遍历的“(iterable)。

ES6明确,暗中认可的Iterator接口安顿在数据结构的Symbol.iterator本性,或然说,3个数据结构只要持有Symbol.iterator性子,就足以以为是“可遍历的”(iterable)。Symbol.iterator属性本人是3个函数,便是如今数据结构暗中认可的遍历器生成函数。实行这些函数,就能回去叁个遍历器。至于属性名Symbol.iterator,它是一个表明式,重临Symbol对象的iterator天性,那是3个预订义好的、类型为Symbol的卓绝值,所以要放在方括号内。(参见Symbol一章)。

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

地点代码中,对象obj是可遍历的(iterable),因为具有Symbol.iterator属性。推行那性子格,会回到八个遍历器对象。该目的的常有特征正是独具next主意。每一次调用next艺术,都会再次来到一个象征当前成员的消息目的,具备valuedone五个属性。

在ES6中,有3类数据结构原生具备Iterator接口:数组、有个别类似数组的靶子、Set和Map结构。

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 }

地点代码中,变量arr是三个数组,原生就具有遍历器接口,计划在arrSymbol.iterator天性下边。所以,调用这几个性情,就赢得遍历器对象。

上面提到,原生就配备Iterator接口的数据结构有叁类,对于那三类数据结构,不用自个儿写遍历器生成函数,for...of循环会自动遍历它们。除却,其余数据结构(首假设目标)的Iterator接口,都须要团结在Symbol.iterator性子上边安排,那样才会被for...of循环遍历。

目的(Object)之所以未有暗中认可计划Iterator接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不分明的,须求开拓者手动内定。本质上,遍历器是壹种线性管理,对于任何非线性的数据结构,安插遍历器接口,就优秀布置1种线性调换。然而,严苛地说,对象安插遍历器接口并不是很须求,因为那时对象实际被看做Map结构选拔,ES5尚无Map结构,而ES陆原生提供了。

三个对象倘若要有可被for...of循环调用的Iterator接口,就务须在Symbol.iterator的属性上配备遍历器生成方法(原型链上的靶子具备该办法也可)。

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);
}

地点代码是二个类陈设Iterator接口的写法。Symbol.iterator属性对应一个函数,试行后回来当前目的的遍历器对象。

上边是经过遍历器完结指针结构的事例。

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

地方代码首先在构造函数的原型链上安顿Symbol.iterator艺术,调用该方法会重返遍历器对象iterator,调用该目的的next艺术,在重临三个值的同时,自动将中间指针移到下四个实例。

上边是另二个为对象增添Iterator接口的例证。

let obj = {
  data: [ 'hello', 'world' ],
  [Symbol.iterator]() {
    const self = this;
    let index = 0;
    return {
      next() {
        if (index < self.data.length) {
          return {
            value: self.data[index++],
            done: false
          };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

对此类似数组的靶子(存在数值键名和length属性),安排Iterator接口,有一个便捷方法,便是Symbol.iterator主意直接引用数组的Iterator接口。

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

[...document.querySelectorAll('div')] // 可以执行了

下边是接近数组的靶子调用数组的Symbol.iterator办法的例证。

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'
}

瞩目,普通对象陈设数组的Symbol.iterator情势,并无效劳。

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

如果Symbol.iterator主意对应的不是遍历器生成函数(即会回到3个遍历器对象),解释引擎将会报错。

var obj = {};

obj[Symbol.iterator] = () => 1;

[...obj] // TypeError: [] is not a function

上面代码中,变量obj的Symbol.iterator方法对应的不是遍历器生成函数,因而报错。

有了遍历器接口,数据结构就能够用for...of循环遍历(详见下文),也能够运用while循环遍历。

var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
  var x = $result.value;
  // ...
  $result = $iterator.next();
}

亚洲必赢官网 ,上面代码中,ITERABLE意味着某种可遍历的数据结构,$iterator是它的遍历器对象。遍历器对象每趟运动指针(next艺术),都检查一下再次回到值的done属性,若是遍历还没竣事,就活动遍历器对象的指针到下一步(next艺术),不断循环。

数据结构的私下认可Iterator接口

Iterator接口的目的,正是为全部数据结构,提供了一种统一的拜会机制,即for...of循环(详见下文)。当使用for...of循环遍历某种数据结构时,该循环会自动去搜索Iterator接口。

1种数据结构只要布署了Iterator接口,大家就称那种数据结构是”可遍历的“(iterable)。

ES六显明,暗许的Iterator接口布置在数据结构的Symbol.iterator特性,或然说,二个数据结构只要具备Symbol.iterator品质,就足以以为是“可遍历的”(iterable)。Symbol.iterator特性本身是3个函数,正是日前数据结构私下认可的遍历器生成函数。施行那一个函数,就能够重回三个遍历器。至于属性名Symbol.iterator,它是二个表明式,再次回到Symbol对象的iterator属性,那是一个预定义好的、类型为Symbol的尤其值,所以要放在方括号内。(参见Symbol壹章)。

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

地点代码中,对象obj是可遍历的(iterable),因为具有Symbol.iterator属性。推行那个特性,会回到3个遍历器对象。该对象的一贯特征即是具有next主意。每一回调用next艺术,都会回来3个表示当前成员的音信目的,具备valuedone四个属性。

在ES六中,有叁类数据结构原生具有Iterator接口:数组、有些类似数组的靶子、Set和Map结构。

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 }

下边代码中,变量arr是1个数组,原生就全数遍历器接口,布署在arrSymbol.iterator属性下面。所以,调用那么些个性,就获取遍历器对象。

地方提到,原生就安顿Iterator接口的数据结构有叁类,对于那3类数据结构,不用自个儿写遍历器生成函数,for...of循环会自动遍历它们。除了这些之外,其他数据结构(首如若目的)的Iterator接口,都亟需本人在Symbol.iterator属性上边布署,那样才会被for...of巡回遍历。

对象(Object)之所以未有私下认可安插Iterator接口,是因为对象的哪位属性先遍历,哪个属性后遍历是不鲜明的,需求开拓者手动内定。本质上,遍历器是1种线性处理,对于其余非线性的数据结构,铺排遍历器接口,就等于安插1种线性转变。可是,严俊地说,对象安插遍历器接口并不是很须要,因为那时对象实际被用作Map结构接纳,ES五尚未Map结构,而ES陆原生提供了。

八个目的假如要有可被for...of巡回调用的Iterator接口,就必须在Symbol.iterator的性情上配置遍历器生成方法(原型链上的对象具有该办法也可)。

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};
    } else {
      return {done: true, value: undefined};
    }
  }
}

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

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

地点代码是叁个类安排Iterator接口的写法。Symbol.iterator品质对应一个函数,奉行后回去当前线指挥部标的遍历器对象。

上面是透过遍历器落成指针结构的事例。

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

上边代码首先在构造函数的原型链上铺排Symbol.iterator艺术,调用该方法会重回遍历器对象iterator,调用该目的的next措施,在回到1个值的同时,自动将在这之中指针移到下一个实例。

上边是另三个为目的增多Iterator接口的例证。

let obj = {
  data: [ 'hello', 'world' ],
  [Symbol.iterator]() {
    const self = this;
    let index = 0;
    return {
      next() {
        if (index < self.data.length) {
          return {
            value: self.data[index++],
            done: false
          };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

对于接近数组的靶子(存在数值键名和length属性),安排Iterator接口,有1个便捷方法,便是Symbol.iterator主意直接引用数组的Iterator接口。

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

[...document.querySelectorAll('div')] // 可以执行了

上边是接近数组的靶子调用数组的Symbol.iterator办法的例子。

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'
}

瞩目,普通对象安排数组的Symbol.iterator格局,并无意义。

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

如果Symbol.iterator办法对应的不是遍历器生成函数(即会回去2个遍历器对象),解释引擎将会报错。

var obj = {};

obj[Symbol.iterator] = () => 1;

[...obj] // TypeError: [] is not a function

地点代码中,变量obj的Symbol.iterator方法对应的不是遍历器生成函数,由此报错。

有了遍历器接口,数据结构就足以用for...of巡回遍历(详见下文),也能够运用while巡回遍历。

var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
  var x = $result.value;
  // ...
  $result = $iterator.next();
}

地点代码中,ITERABLE意味着某种可遍历的数据结构,$iterator是它的遍历器对象。遍历器对象每趟运动指针(next措施),都检查一下重临值的done本性,假诺遍历还没截止,就活动遍历器对象的指针到下一步(next措施),不断循环。

调用Iterator接口的场子

有壹对地方会暗中同意调用Iterator接口(即Symbol.iterator艺术),除了下文子禽介绍的for...of循环,还有多少个其余场馆。

(1)解构赋值

对数组和Set结构实行解构赋值时,会默许调用Symbol.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'];

(二)扩大运算符

恢宏运算符(…)也会调用默许的iterator接口。

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

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

地点代码的壮流年算符内部就调用Iterator接口。

实际,这提供了1种方便人民群众机制,能够将其他布置了Iterator接口的数据结构,转为数组。也正是说,只要有些数据结构布署了Iterator接口,就足以对它应用扩展运算符,将其转为数组。

let arr = [...iterable];

(3)yield*

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
  • Array.from()
  • Map(), Set(), WeakMap(),
    WeakSet()(比如new Map([['a',1],['b',2]])
  • Promise.all()
  • Promise.race()

调用Iterator接口的场所

有一部分场子会暗中同意调用Iterator接口(即Symbol.iterator方法),除了下文仲介绍的for...of循环,还有多少个其他场地。

(壹)解构赋值

对数组和Set结构进行解构赋值时,会暗许调用Symbol.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'];

(二)扩充运算符

扩展运算符(…)也会调用暗中认可的iterator接口。

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

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

地方代码的恢弘运算符内部就调用Iterator接口。

实则,那提供了壹种便利机制,能够将其他布署了Iterator接口的数据结构,转为数组。也便是说,只要有些数据结构陈设了Iterator接口,就能够对它选择扩展运算符,将其转为数组。

let arr = [...iterable];

(3)yield*

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
  • Array.from()
  • Map(), Set(), WeakMap(),
    WeakSet()(比如new Map([['a',1],['b',2]])
  • Promise.all()
  • Promise.race()

字符串的Iterator接口

字符串是三个近似数组的目的,也原生具备Iterator接口。

var someString = "hi";
typeof someString[Symbol.iterator]
// "function"

var iterator = someString[Symbol.iterator]();

iterator.next()  // { value: "h", done: false }
iterator.next()  // { value: "i", done: false }
iterator.next()  // { value: undefined, done: true }

地点代码中,调用Symbol.iterator方法重临一个遍历器对象,在这些遍历器上得以调用next方法,达成对于字符串的遍历。

能够覆盖原生的Symbol.iterator格局,到达修改遍历器行为的目的。

var str = new String("hi");

[...str] // ["h", "i"]

str[Symbol.iterator] = function() {
  return {
    next: function() {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    _first: true
  };
};

[...str] // ["bye"]
str // "hi"

上边代码中,字符串str的Symbol.iterator艺术被退换了,所以扩充运算符(...)重返的值形成了bye,而字符串自己仍然hi

字符串的Iterator接口

字符串是三个接近数组的目标,也原生具备Iterator接口。

var someString = "hi";
typeof someString[Symbol.iterator]
// "function"

var iterator = someString[Symbol.iterator]();

iterator.next()  // { value: "h", done: false }
iterator.next()  // { value: "i", done: false }
iterator.next()  // { value: undefined, done: true }

地点代码中,调用Symbol.iterator格局重回3个遍历器对象,在那么些遍历器上能够调用next方法,达成对于字符串的遍历。

能够覆盖原生的Symbol.iterator格局,到达修改遍历器行为的目的。

var str = new String("hi");

[...str] // ["h", "i"]

str[Symbol.iterator] = function() {
  return {
    next: function() {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    _first: true
  };
};

[...str] // ["bye"]
str // "hi"

下边代码中,字符串str的Symbol.iterator艺术被更换了,所以扩充运算符(...)重返的值形成了bye,而字符串自己依旧hi

Iterator接口与Generator函数

Symbol.iterator艺术的最简单易行完毕,依然选取下壹章要介绍的Generator函数。

var myIterable = {};

myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};
[...myIterable] // [1, 2, 3]

// 或者采用下面的简洁写法

let obj = {
  * [Symbol.iterator]() {
    yield 'hello';
    yield 'world';
  }
};

for (let x of obj) {
  console.log(x);
}
// hello
// world

上边代码中,Symbol.iterator艺术差不离不用布置任何代码,只要用yield命令给出每一步的重临值就可以。

Iterator接口与Generator函数

Symbol.iterator主意的最简易达成,依然利用下壹章要介绍的Generator函数。

var myIterable = {};

myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};
[...myIterable] // [1, 2, 3]

// 或者采用下面的简洁写法

let obj = {
  * [Symbol.iterator]() {
    yield 'hello';
    yield 'world';
  }
};

for (let x of obj) {
  console.log(x);
}
// hello
// world

地方代码中,Symbol.iterator主意大概不用布置任何代码,只要用yield命令给出每一步的重返值就能够。

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

遍历器对象除了具备next措施,还足以有所return方法和throw情势。若是你协和写遍历器对象生成函数,那么next措施是必须布置的,return方法和throw格局是不是布署是可选的。

return办法的选拔场馆是,假使for...of循环提前退出(常常是因为出错,或然有break语句或continue话语),就能调用return措施。若是一个目标在成就遍历前,要求清理或释放能源,就足以安插return方法。

function readLinesSync(file) {
  return {
    next() {
      if (file.isAtEndOfFile()) {
        file.close();
        return { done: true };
      }
    },
    return() {
      file.close();
      return { done: true };
    },
  };
}

地方代码中,函数readLinesSync接受二个文件对象作为参数,再次回到1个遍历器对象,个中除了next方法,还布署了return主意。下边,大家让文件的遍历提前再次来到,那样就能接触施行return方法。

for (let line of readLinesSync(fileName)) {
  console.log(line);
  break;
}

注意,return方法必须再次来到三个目的,那是Generator规格决定的。

throw艺术首就算协作Generator函数使用,一般的遍历器对象用不到那个情势。请参阅《Generator函数》1章。

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

遍历器对象除了具备next方法,仍是可以具备return方法和throw主意。若是您本身写遍历器对象生成函数,那么next方式是必须配备的,return方法和throw主意是还是不是配备是可选的。

return艺术的使用场地是,倘诺for...of循环提前退出(平时是因为出错,恐怕有break语句或continue话语),就能够调用return格局。假诺一个对象在成就遍历前,要求清理或自由能源,就足以布置return方法。

function readLinesSync(file) {
  return {
    next() {
      if (file.isAtEndOfFile()) {
        file.close();
        return { done: true };
      }
    },
    return() {
      file.close();
      return { done: true };
    },
  };
}

地点代码中,函数readLinesSync经受1个文件对象作为参数,再次回到二个遍历器对象,当中除了next主意,还陈设了return格局。上边,我们让文件的遍历提前再次回到,这样就可以接触推行return方法。

for (let line of readLinesSync(fileName)) {
  console.log(line);
  break;
}

注意,return主意必须回到三个目的,那是Generator规格决定的。

throw方法首如若相配Generator函数使用,一般的遍历器对象用不到这么些点子。请参阅《Generator函数》1章。

for…of循环

ES6 借鉴 C++、Java、C# 和 Python
语言,引入了for...of循环,作为遍历全部数据结构的联结的艺术。

八个数据结构只要铺排了Symbol.iterator特性,就被视为具备iterator接口,就能够用for...of循环遍历它的成员。也正是说,for...of循环之中调用的是数据结构的Symbol.iterator方法。

for...of巡回能够选用的限定包蕴数组、Set 和 Map
结构、有些类似数组的目的(比方arguments对象、DOM NodeList
对象)、后文的 Generator 对象,以及字符串。

for…of循环

ES6 借鉴 C++、Java、C# 和 Python
语言,引入了for...of巡回,作为遍历全部数据结构的统一的措施。

一个数据结构只要布署了Symbol.iterator品质,就被视为具备iterator接口,就能够用for...of循环遍历它的成员。也正是说,for...of巡回之中调用的是数据结构的Symbol.iterator方法。

for...of巡回能够使用的范围包罗数组、Set 和 Map
结构、某个类似数组的对象(比方arguments对象、DOM NodeList
对象)、后文的 Generator 对象,以及字符串。

数组

数组原生具备iterator接口(即暗许铺排了Symbol.iterator属性),for...of循环本质上正是调用那一个接口发生的遍历器,能够用下边包车型大巴代码阐明。

const arr = ['red', 'green', 'blue'];

for(let v of arr) {
  console.log(v); // red green blue
}

const obj = {};
obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr);

for(let v of obj) {
  console.log(v); // red green blue
}

上边代码中,空对象obj陈设了数组arrSymbol.iterator属性,结果objfor...of巡回,发生了与arr统统壹致的结果。

for...of巡回能够代表数组实例的forEach方法。

const arr = ['red', 'green', 'blue'];

arr.forEach(function (element, index) {
  console.log(element); // red green blue
  console.log(index);   // 0 1 2
});

JavaScript原有的for...in循环,只好赚取对象的键名,不可能一贯获得键值。ES6提供for...of巡回,允许遍历获得键值。

var arr = ['a', 'b', 'c', 'd'];

for (let a in arr) {
  console.log(a); // 0 1 2 3
}

for (let a of arr) {
  console.log(a); // a b c d
}

地点代码注脚,for...in巡回读取键名,for...of巡回读取键值。假使要经过for...of巡回,获取数组的目录,能够依据数组实例的entries方法和keys艺术,参见《数组的庞大》章节。

for...of循环调用遍历器接口,数组的遍历器接口只回去具备数字索引的性质。这点跟for...in循环也差别等。

let arr = [3, 5, 7];
arr.foo = 'hello';

for (let i in arr) {
  console.log(i); // "0", "1", "2", "foo"
}

for (let i of arr) {
  console.log(i); //  "3", "5", "7"
}

上边代码中,for...of循环不会再次回到数组arrfoo属性。

数组

数组原生具有iterator接口(即暗中认可安顿了Symbol.iterator属性),for...of循环本质上正是调用那么些接口发生的遍历器,能够用上面包车型地铁代码注解。

const arr = ['red', 'green', 'blue'];

for(let v of arr) {
  console.log(v); // red green blue
}

const obj = {};
obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr);

for(let v of obj) {
  console.log(v); // red green blue
}

地方代码中,空对象obj布局了数组arrSymbol.iterator属性,结果objfor...of巡回,产生了与arr一起一样的结果。

for...of循环可以代表数组实例的forEach方法。

const arr = ['red', 'green', 'blue'];

arr.forEach(function (element, index) {
  console.log(element); // red green blue
  console.log(index);   // 0 1 2
});

JavaScript原有的for...in巡回,只好获取对象的键名,不可能直接得到键值。ES六提供for...of循环,允许遍历获得键值。

var arr = ['a', 'b', 'c', 'd'];

for (let a in arr) {
  console.log(a); // 0 1 2 3
}

for (let a of arr) {
  console.log(a); // a b c d
}

上边代码声明,for...in循环读取键名,for...of巡回读取键值。假如要通过for...of循环,获取数组的目录,能够依附数组实例的entries方法和keys格局,参见《数组的扩展》章节。

for...of循环调用遍历器接口,数组的遍历器接口只回去具备数字索引的品质。这点跟for...in循环也不雷同。

let arr = [3, 5, 7];
arr.foo = 'hello';

for (let i in arr) {
  console.log(i); // "0", "1", "2", "foo"
}

for (let i of arr) {
  console.log(i); //  "3", "5", "7"
}

上面代码中,for...of循环不会回来数组arrfoo属性。

Set和Map结构

Set 和 Map 结构也原生具备 Iterator 接口,能够间接采取for...of循环。

var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
  console.log(e);
}
// Gecko
// Trident
// Webkit

var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for (var [name, value] of es6) {
  console.log(name + ": " + value);
}
// edition: 6
// committee: TC39
// standard: ECMA-262

上边代码演示了怎么遍历 Set 结商谈 Map
结构。值得注意的地方有三个,首先,遍历的各类是依照顺序成员被增多进数据结构的依次。其次,Set
结构遍历时,重临的是三个值,而 Map
结构遍历时,再次回到的是3个数组,该数组的五个成员分头为当下 Map
成员的键名和键值。

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
  console.log(pair);
}
// ['a', 1]
// ['b', 2]

for (let [key, value] of map) {
  console.log(key + ' : ' + value);
}
// a : 1
// b : 2

Set和Map结构

Set 和 Map 结构也原生具备 Iterator 接口,能够一向动用for...of循环。

var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
  console.log(e);
}
// Gecko
// Trident
// Webkit

var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for (var [name, value] of es6) {
  console.log(name + ": " + value);
}
// edition: 6
// committee: TC39
// standard: ECMA-262

下面代码演示了何等遍历 Set 结议和 Map
结构。值得注意的地点有七个,首先,遍历的种种是依照顺序成员被增多进数据结构的逐条。其次,Set
结构遍历时,再次来到的是3个值,而 Map
结构遍历时,重临的是二个数组,该数组的五个分子分头为当前 Map
成员的键名和键值。

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
  console.log(pair);
}
// ['a', 1]
// ['b', 2]

for (let [key, value] of map) {
  console.log(key + ' : ' + value);
}
// a : 1
// b : 2

计量生成的数据结构

稍微数据结构是在存活数据结构的根基上,总计生成的。比如,ES6的数组、Set、Map
都配备了以下多个主意,调用后都回去遍历器对象。

  • entries() 再次回到3个遍历器对象,用来遍历[键名, 键值]构成的数组。对于数组,键名就是索引值;对于
    Set,键名与键值相同。Map 结构的 Iterator
    接口,私下认可正是调用entries方法。
  • keys() 重回二个遍历器对象,用来遍历全体的键名。
  • values() 再次回到1个遍历器对象,用来遍历所有的键值。

那四个办法调用后变化的遍历器对象,所遍历的都以总括生成的数据结构。

let arr = ['a', 'b', 'c'];
for (let pair of arr.entries()) {
  console.log(pair);
}
// [0, 'a']
// [1, 'b']
// [2, 'c']

测算生成的数据结构

稍许数据结构是在存活数据结构的基本功上,总括生成的。比方,ES6的数组、Set、Map
都布署了以下七个办法,调用后都回到遍历器对象。

  • entries() 重回五个遍历器对象,用来遍历[键名, 键值]重组的数组。对于数组,键名就是索引值;对于
    Set,键名与键值同样。Map 结构的 Iterator
    接口,默许便是调用entries方法。
  • keys() 重回一个遍历器对象,用来遍历全数的键名。
  • values() 重返1个遍历器对象,用来遍历全部的键值。

这三个方法调用后转换的遍历器对象,所遍历的都是计量生成的数据结构。

let arr = ['a', 'b', 'c'];
for (let pair of arr.entries()) {
  console.log(pair);
}
// [0, 'a']
// [1, 'b']
// [2, 'c']

好像数组的目的

接近数组的对象包蕴一些类。上边是for...of循环用于字符串、DOM NodeList
对象、arguments对象的例证。

// 字符串
let str = "hello";

for (let s of str) {
  console.log(s); // h e l l o
}

// DOM NodeList对象
let paras = document.querySelectorAll("p");

for (let p of paras) {
  p.classList.add("test");
}

// arguments对象
function printArgs() {
  for (let x of arguments) {
    console.log(x);
  }
}
printArgs('a', 'b');
// 'a'
// 'b'

对于字符串来讲,for...of循环还有3个特色,就是会不错识别3一个人 UTF-1陆字符。

for (let x of 'a\uD83D\uDC0A') {
  console.log(x);
}
// 'a'
// '\uD83D\uDC0A'

并不是具有类似数组的目的都负有 Iterator
接口,三个便当的缓和方法,正是应用Array.from艺术将其转为数组。

let arrayLike = { length: 2, 0: 'a', 1: 'b' };

// 报错
for (let x of arrayLike) {
  console.log(x);
}

// 正确
for (let x of Array.from(arrayLike)) {
  console.log(x);
}

接近数组的对象

类似数组的靶子包罗某个类。下边是for...of巡回用于字符串、DOM NodeList
对象、arguments目标的例子。

// 字符串
let str = "hello";

for (let s of str) {
  console.log(s); // h e l l o
}

// DOM NodeList对象
let paras = document.querySelectorAll("p");

for (let p of paras) {
  p.classList.add("test");
}

// arguments对象
function printArgs() {
  for (let x of arguments) {
    console.log(x);
  }
}
printArgs('a', 'b');
// 'a'
// 'b'

对于字符串来讲,for...of巡回还有三个表征,正是会不错识别3几人 UTF-1陆字符。

for (let x of 'a\uD83D\uDC0A') {
  console.log(x);
}
// 'a'
// '\uD83D\uDC0A'

并不是兼备类似数组的对象都兼备 Iterator
接口,1个便利的化解方法,正是使用Array.from方法将其转为数组。

let arrayLike = { length: 2, 0: 'a', 1: 'b' };

// 报错
for (let x of arrayLike) {
  console.log(x);
}

// 正确
for (let x of Array.from(arrayLike)) {
  console.log(x);
}

对象

对于常见的靶子,for...of布局不可能一向动用,会报错,必须配备了 Iterator
接口后本领应用。不过,那样情况下,for...in巡回照旧得以用来遍历键名。

let es6 = {
  edition: 6,
  committee: "TC39",
  standard: "ECMA-262"
};

for (let e in es6) {
  console.log(e);
}
// edition
// committee
// standard

for (let e of es6) {
  console.log(e);
}
// TypeError: es6 is not iterable

地点代码表示,对于常见的对象,for...in巡回能够遍历键名,for...of循环会报错。

一种缓慢解决形式是,使用Object.keys办法将目标的键名生成三个数组,然后遍历这几个数组。

for (var key of Object.keys(someObject)) {
  console.log(key + ': ' + someObject[key]);
}

另多少个艺术是采取 Generator 函数将目标重新打包一下。

function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

for (let [key, value] of entries(obj)) {
  console.log(key, '->', value);
}
// a -> 1
// b -> 2
// c -> 3

对象

对此一般的目标,for...of组织无法直接行使,会报错,必须配备了 Iterator
接口后本领选拔。不过,那样情况下,for...in循环如故能够用来遍历键名。

let es6 = {
  edition: 6,
  committee: "TC39",
  standard: "ECMA-262"
};

for (let e in es6) {
  console.log(e);
}
// edition
// committee
// standard

for (let e of es6) {
  console.log(e);
}
// TypeError: es6 is not iterable

上边代码表示,对于常见的靶子,for...in循环可以遍历键名,for...of循环会报错。

壹种缓和措施是,使用Object.keys方法将对象的键名生成多少个数组,然后遍历那几个数组。

for (var key of Object.keys(someObject)) {
  console.log(key + ': ' + someObject[key]);
}

另2个措施是行使 Generator 函数将对象重新包装一下。

function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

for (let [key, value] of entries(obj)) {
  console.log(key, '->', value);
}
// a -> 1
// b -> 2
// c -> 3

与其余遍历语法的相比

以数组为例,JavaScript 提供多种遍历语法。最原始的写法正是for循环。

for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index]);
}

那种写法相比较麻烦,因而数组提供放置的forEach方法。

myArray.forEach(function (value) {
  console.log(value);
});

那种写法的难题在于,无法中途跳出forEach循环,break命令或return一声令下都无法一蹴而就。

for...in巡回能够遍历数组的键名。

for (var index in myArray) {
  console.log(myArray[index]);
}

for...in巡回有多少个毛病。

  • 数组的键名是数字,可是for...in巡回是以字符串作为键名“0”、“1”、“②”等等。
  • for...in循环不仅遍历数字键名,还会遍历手动加多的其余键,以至包蕴原型链上的键。
  • 一些情状下,for...in循环会以自由顺序遍历键名。

总之,for...in循环主即使为遍历对象而规划的,不适用于遍历数组。

for...of巡回相比较下面两种做法,有一些明明的帮助和益处。

for (let value of myArray) {
  console.log(value);
}
  • 有着同for...in如出壹辙的凝练语法,不过并未有for...in那多个缺点。
  • 不等用于forEach格局,它能够与breakcontinuereturn合作使用。
  • 提供了遍历全体数据结构的相会操作接口。

下边是一个选用break语句,跳出for...of循环的例证。

for (var n of fibonacci) {
  if (n > 1000)
    break;
  console.log(n);
}

下面的例子,会输出斐波纳契数列小于等于一千的项。如若当前项高于一千,就能够选拔break言辞跳出for...of循环。

与别的遍历语法的相比

以数组为例,JavaScript 提供多种遍历语法。最原始的写法便是for循环。

for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index]);
}

那种写法相比麻烦,因而数组提供放置的forEach方法。

myArray.forEach(function (value) {
  console.log(value);
});

那种写法的主题材料在于,无法中途跳出forEach循环,break命令或return一声令下都不可能一蹴而就。

for...in循环能够遍历数组的键名。

for (var index in myArray) {
  console.log(myArray[index]);
}

for...in循环有多少个缺陷。

  • 数组的键名是数字,不过for...in巡回是以字符串作为键名“0”、“壹”、“2”等等。
  • for...in循环不仅遍历数字键名,还会遍历手动增多的其余键,乃至席卷原型链上的键。
  • 有个别情形下,for...in循环会以随机顺序遍历键名。

总之,for...in循环首假设为遍历对象而规划的,不适用于遍历数组。

for...of巡回比较上面两种做法,有1部分分明的独到之处。

for (let value of myArray) {
  console.log(value);
}
  • 有着同for...in同样的简洁语法,不过从未for...in那个缺点。
  • 不等用于forEach措施,它能够与breakcontinuereturn万分使用。
  • 提供了遍历全体数据结构的统①操作接口。

上边是一个行使break语句,跳出for...of巡回的例证。

for (var n of fibonacci) {
  if (n > 1000)
    break;
  console.log(n);
}

上边的例证,会输出斐波纳契数列小于等于1000的项。假设当前项高于一千,就能够采取break讲话跳出for...of循环。

网站地图xml地图