es6 语法 (iterator和for...of循环)

2019-05-03 22:47 来源:未知

Iterator遍历器

遍历器(Iterator)便是那样一种体制。它是1种接口,为各样不相同的数据结构提供联合的访问机制。任何数据结构只要安插Iterator接口,就足以做到遍历操作(即依次拍卖该数据结构的享有成员)。

作用:

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

Iterator的遍历过程:

(一)创造二个指针对象,指向当前数据结构的开场地点。相当于说,遍历器对象本质上,正是二个指南针对象。

(二)第3次调用指针对象的next主意,能够将指针指向数据结构的首先个分子。

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

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

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

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

Iterator和for...of循环

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

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),ES陆又增添了Map和Set。那样就有了三种多少会集,用户还是能构成使用它们,定义自个儿的数据结构,比如数组的分子是Map,Map的分子是目的。那样就要求一种统一的接口机制,来拍卖全部分裂的数据结构。

遍历器(Iterator)正是这么1种体制。它是一种接口,为各类差别的数据结构提供联合的拜会机制。任何数据结构只要铺排Iterator接口,就可以完成遍历操作(即依次拍卖该数据结构的有着成员)。

Iterator的作用有多少个:壹是为种种数据结构,提供七个合并的、简便的访问接口;贰是驱动数据结构的分子能够按某种次序排列;3是ES六创办了壹种新的遍历命令for...of循环,Iterator接口首要供for...of消费。

Iterator的遍历进程是如此的。

(一)创造贰个指南针对象,指向当前数据结构的前奏地方。相当于说,遍历器对象本质上,正是三个指南针对象。

(二)第二遍调用指针对象的next主意,能够将指针指向数据结构的首先个分子。

(三)首回调用指针对象的next办法,指针就对准数据结构的第2个成员。

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

每3次调用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};
    }
  };
}

地方代码定义了二个makeIterator函数,它是三个遍历器生成函数,效率正是重回三个遍历器对象。对数组['a', 'b']施行那一个函数,就能回到该数组的遍历器对象(即指针对象)it

指南针对象的next方法,用来运动指针。初始时,指针指向数组的起来地方。然后,每趟调用next艺术,指针就能够指向数组的下二个分子。首回调用,指向a;第二回调用,指向b

next艺术再次来到一个对象,表示近来数据成员的音信。这一个目的具有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,再次回到二个遍历器对象(即指针对象)。可是并不曾对应的数据结构,可能说,遍历器对象自个儿描述了贰个数据结构出来。

在ES陆中,有些数据结构原生具有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,
}

数据结构的暗中认可Iterator接口

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

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

ES陆规定,暗中同意的Iterator接口陈设在数据结构的Symbol.iterator属性,大概说,3个数据结构只要具有Symbol.iterator属性,就足以认为是“可遍历的”(iterable)。Symbol.iterator品质自己是2个函数,正是目前数据结构私下认可的遍历器生成函数。施行那几个函数,就能够回来1个遍历器。至于属性名Symbol.iterator,它是3个表明式,重临Symbol对象的iterator特性,那是2个预订义好的、类型为Symbol的独特值,所以要放在方括号内。(参见Symbol1章)。

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

上边代码中,对象obj是可遍历的(iterable),因为全部Symbol.iterator脾气。实践那特特性,会重回多少个遍历器对象。该目的的根本特征正是全体next办法。每趟调用next措施,都会回去三个意味当前成员的音信目标,具备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是2个数组,原生就全体遍历器接口,铺排在arrSymbol.iterator性格下面。所以,调用这几个天性,就获取遍历器对象。

地方提到,原生就配备Iterator接口的数据结构有3类,对于那3类数据结构,不用自个儿写遍历器生成函数,for...of循环会自动遍历它们。除此而外,别的数据结构(首如果目标)的Iterator接口,都亟需和谐在Symbol.iterator品质上边安顿,那样才会被for...of巡回遍历。

目的(Object)之所以未有暗中认可计划Iterator接口,是因为对象的哪些属性先遍历,哪个属性后遍历是不明确的,必要开拓者手动钦命。本质上,遍历器是壹种线性管理,对于别的非线性的数据结构,安插遍历器接口,就约等于布署壹种线性转变。可是,严厉地说,对象安插遍历器接口并不是很须求,因为那时候对象实际被看作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);
}

地点代码是1个类安顿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措施,在回到多个值的还要,自动将个中指针移到下四个实例。

上面是另3个为目标加多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接口,有2个简便方法,正是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接口(即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'];

(2)扩充运算符

恢宏运算符(...)也会调用暗中同意的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 }

(4)别的地方

是因为数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场面,其实都调用了遍历器接口。上边是一些例证。

  • 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接口与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收受五个文书对象作为参数,再次来到三个遍历器对象,当中除了next办法,还铺排了return措施。下边,咱们让文件的遍历提前重返,那样就能够接触执行return方法。

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

注意,return办法必须回到1个目的,这是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 对象,以及字符串。

数组

数组原生具备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 结构遍历时,再次回到的是三个数组,该数组的八个成员分头为当前 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

计量生成的数据结构

有些数据结构是在现存数据结构的根基上,计算生成的。比如,ES陆的数组、Set、Map 都安顿了以下多少个方法,调用后都回去遍历器对象。

  • entries() 重返贰个遍历器对象,用来遍历[键名, 键值]组成的数组。对于数组,键名就是索引值;对于 Set,键名与键值同样。Map 结构的 Iterator 接口,暗中认可正是调用entries方法。
  • keys() 再次来到三个遍历器对象,用来遍历所有的键名。
  • values() 再次来到三个遍历器对象,用来遍历全部的键值。

那四个方法调用后改动的遍历器对象,所遍历的都以持筹握算生成的数据结构。

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巡回还有2个表征,就是会正确识别三11人 UTF-1陆字符。

for (let x of 'auD83DuDC0A') {
  console.log(x);
}
// 'a'
// 'uD83DuDC0A'

并不是享有类似数组的目的都具备 Iterator 接口,2个便捷的消除办法,正是接纳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循环会报错。

1种减轻方法是,使用Object.keys主意将目的的键名生成1个数组,然后遍历那几个数组。

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

与任何遍历语法的可比

以数组为例,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”、“一”、“贰”等等。
  • 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);
}

地点的例子,会输出斐波纳契数列小于等于一千的项。倘使当前项高于1000,就能选取break言辞跳出for...of循环。

TAG标签: 韦德娱乐1946
版权声明:本文由韦德娱乐1946_韦德娱乐1946网页版|韦德国际1946官网发布于韦德娱乐1946网页版,转载请注明出处:es6 语法 (iterator和for...of循环)