当前位置:K88软件开发文章中心编程语言JavaScriptECMAScript → 文章内容

ECMAScript 6 Iterator和for...of循环

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 15:38:36

Set()(比如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(x); break;}注意,return方法必须返回一个对象,这是Generator规格决定的。throw方法主要是配合Generator函数使用,一般的遍历器对象用不到这个方法。请参阅《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接口,for...of循环本质上就是调用这个接口产生的遍历器,可以用下面的代码证明。const arr = ['red', 'green', 'blue'];let iterator = arr[Symbol.iterator]();for(let v of arr) { console.log(v); // red green blue}for(let v of iterator) { console.log(v); // red green blue}上面代码的for...of循环的两种写法是等价的。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循环不会返回数组arr的foo属性。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// Webkitvar 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计算生成的数据结构有些数据结构是在现有数据结构的基础上,计算生成的。比如,ES6的数组、Set、Map都部署了以下三个方法,调用后都返回

上一页  [1] [2] [3] [4]  下一页


ECMAScript 6 Iterator和for...of循环