ES6()
一、Iterator和for...of循环
1.Iterator遍历器
- 一是为各种数据结构,提供一个统一的、简便的访问接口
- 二是使得数据结构的成员能够按某种次序排列
- Iterator 接口主要供
for...of
消费目前知道四种数据集合(Array、Object、Map、Set)
使用方式:
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
(2)第一次调用指针对象的
next
方法,可以将指针指向数据结构的第一个成员。(3)第二次调用指针对象的
next
方法,指针就指向数据结构的第二个成员。(4)不断调用指针对象的
next
方法,直到它指向数据结构的结束位置。返回value(成员值)和done(布尔值:表示遍历是否结束)
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};//两个属性都是可以省略}};
}
没有对应的数据结构,遍历器对象会自己描述了一个数据结构出来
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};}};
}
2. 默认接口
ES6 规定,一个数据结构只要具有
Symbol.iterator
属性,就可以认为是“可遍历的”
const obj = {[Symbol.iterator] : function () {return {next: function () {return {value: 1,done: true};}};}
};
原生具备 Iterator 接口的数据结构如下 :
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
3. for...of循环
个数据结构只要部署了
Symbol.iterator
属性,就被视为具有 iterator 接口,就可以用for...of
循环遍历它的成员。也就是说,for...of
循环内部调用的是数据结构的Symbol.iterator
方法替代forEach方法
使用范围:
Set 和 Map 结构、某些类似数组的对象(比如arguments
对象、DOM NodeList 对象)、 Generator 对象,以及字符串
数组:
for...in
循环读取键名(下标)for...of
循环读取键值- 可以借助数组实例的
entries
方法和keys
方法
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
}
Set和Map
ar 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
类数组对象和字符串
// 字符串
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(需要遍历器接口),可以直接使用for...in
let es6 = {edition: 6,committee: "TC39",standard: "ECMA-262"
};for (let e in es6) {console.log(e);
}
// edition
// committee
// standardfor (let e of es6) {console.log(e);
}
// TypeError: es6[Symbol.iterator] is not a function//--------------------------------------------
解决方法:将对象转为数组
for (var key of Object.keys(someObject)) {console.log(key + ': ' + someObject[key]);
}
二、 Generator 函数
1.Generator函数的说明与使用
Generator 函数是一个状态机,封装了多个内部状态;
执行 Generator 函数会返回一个遍历器对象
Generator 函数是一个普通函数,
function
关键字与函数名之间有一个星号- 函数体内部使用
yield
表达式function* helloWorldGenerator() {yield 'hello';yield 'world';return 'ending'; }var hw = helloWorldGenerator();
Generator函数就算使用函数调用方式不会直接执行,需要next方法:每次调用时候调用一次方法
yield
表达式是暂停执行的标记,而next
方法可以恢复执行
hw.next()
// { value: 'hello', done: false }hw.next()
// { value: 'world', done: false }hw.next()
// { value: 'ending', done: true }hw.next()
// { value: undefined, done: true }
2.yield表达式
- 遇到
yield
表达式,就暂停执行后面的操作- 下一次调用
next
方法时,再继续往下执行- 如果没有再遇到新的
yield
表达式,就一直运行到函数结束,直到return
语句为止- 如果该函数没有
return
语句,则返回的对象的value
属性值为undefined
3. 场景:为了不具备Interator接口的对象提供遍历操作
const obj = {name: "haha",age: 18,};obj[Symbol.iterator] = objectEntries; //生成器function* objectEntries(obj) {// 获取对象那个的所有的key// 保存到数组中const propKeys = Object.keys(obj); //获取对象中的所有keyfor (const propkey of propKeys) {// 生成器键值对yield [propkey, obj[propkey]];}}console.log(obj);//生成器生成之后for (let [key, value] of objectEntries(obj)) {console.log(`${key},${value} `);}