ES6——Iterator原理及使用方法:
先了解一下Symbol:(第七种数据结构)
特点:唯一、可作为对象的属性,有静属性Symbol.iterator;
demo:
const os = Symbol(‘abc’); //赋值;
const os2 = Symbol(‘abc’);
const prop = ‘name’;
const obj = {
[prop] : 'ly', //ES6中可以将字符串作为属性名,注意写法;
[os] : 'll',
[os2] : 'll2'
}
console.log(obj[prop]); //==> ‘ly’; //注意取值时的方法;
console.log(obj[os]); //==> ‘ll’;
console.log(obj[os2]); //==> ‘ll2’;
console.log(os == os2); //==> false;
console.log( Symbol.iterator, Symbol(‘Symbol.iterator’));
//==> Symbol(Symbol.iterator), Symbol(Symbol.iterator);
//可见虽然os、os2赋的值一样,但是后面的值不会覆盖前面;
Iterator:(是一个函数)
相关知识点:
迭代模式:提供一种方法可以顺序获得聚合对象中的各个元素,是一种简单也是最常见的设计模式,它可以让用户通过特定的接口巡访集合中的每一个元素而不用了解底层的实现;
迭代器:依照迭代模式的思想而实现,分为内部迭代器和外部迭代器;
内部迭代器:本身是函数,该函数内部定义好了迭代规则,完全接手整个跌倒过程,外部只需一次初始调用;(forEach() 、 jQuery.each())
外部迭代器:本身是函数,执行返回迭代对象,迭代下一个元素必须显示调用,调用复杂度增加,但灵活性强;(function outerIterator () {})
迭代器的目的:从迭代模式思想中可以看出,就是要标准化迭代操作;
举个例子:服务器端提供数组数据给前端,前端for循环遍历,但由于业务变化,使得数据结构发生改变,返回对象后者set map,导致前端遍历代码大量重写;
解决方案:ES6中引入Iterator,部署在NodeList、arguments、Array、Set、Map、String上等数据的Symbol.iterator的属性;使得这些数据是iterable可迭代的,能进行for of、…、Array.from等操作;
demo:
const arr = [1, 2, 3];
console.log([...arr]); // ==> [1, 2, 3];
但是有些数据原型上没有Symbol.iterator方法,无法使用该迭代操作者,需要手动封装;
以一个对象为例进行封装:
const obj = {
0 : 'a',
1 : 'b',
2 : 'c',
length : 3,
[Symbol.iterator] : function () {
//将Symbol.iterator作为属性,
//原理就是function outerIterator () {}方法;
let curIndex = 0;
const next = () => {
return {
value : this[curIndex],
done : this.length == curIndex++,
}
}
return {
next
}
}
}
//测试:
console.log([...obj]);
//可以使用...方法,结果为["a", "b", "c"];
for (let p of obj){
console.log(p);
//for of 方法同样可以执行;
}
Generator封装方法:(简化代码)
Generator简介:生成器,本身是函数,执行后返回迭代对象,函数内部要配合yield使用,Generator函数会分段执行,遇到yield即暂停;
Generator特点:function和函数名之间需带 *;函数体内部yield表达式,产出不同的内部状态(值);
由于生成器Generator可以返回一个迭代对象,可利用该特点替换之前的封装的Symbol.iterator方法:
const obj1 = {
0 : 'a',
1 : 'b',
2 : 'c',
length : 3,
[Symbol.iterator] : function * () {
let curIndex = 0;
while (curIndex != this.length) {
yield this[curIndex];
curIndex++
}
}
}
console.log([...obj1]) //可以使用...方法,结果为["a", "b", "c"];
for (let p of obj1){
console.log(p)
}
//拓展:Generator的使用:
function * test () {
const value1 = yield 'a';
console.log(value1);
const value2 = yield 'b';
console.log(value2);
const value3 = yield 'c';
console.log(value3);
return 'd';
}
// function * test () {
// yield 'a';
// console.log(1);
// yield 'b';
// console.log(2);
// yield 'c';
// console.log(3);
// return 'd';
// }
const oG = test();
console.log(oG.next(1)); //会分段执行;
console.log(oG.next(2)); //会分段执行;
console.log(oG.next(3)); //会分段执行;
console.log(oG.next(4)); //会分段执行;
输出结果: