本文共 5535 字,大约阅读时间需要 18 分钟。
1.什么是迭代?
将数据按照一定的顺序依次取出的过程叫迭代 迭代能将数据依次取出但是不能保证数据全部取出,也不能确定取出的个数 2.什么是迭代器? 对迭代过程的封装对象。 迭代器拥拥有获取下一个数据的功能 在返回的数据中存在有数据状态,判断是否可以继续向下继续迭代。 3.js中规定的迭代器 js中规定 一个对象中 含有next方法 并且这个next方法返回一个对象 那么我们就认为这个对象为迭代器var obj = { next() { // 用于获取下一个值 return { // 返回的数据 value : "测试", // 判断是否继续 done : false } } }
接下来我们来写一个自定义的迭代器(数组)
let arr = [1,2,3,4]; // isiterator(迭代器) const isiterator = { // 声明变量让它从0开始迭代 num : 0, next() { var result = { value : arr[this.num], // 设置迭代状态 (是否继续) done : this.num >= arr.length } this.num++; return result; } } console.log(isiterator); // 调用next每次取出对应的状态和值 console.log(isiterator.next());
每调用一次就会取出一个值,在这里return运用了闭包的原理
试着封装一下自定义数组的迭代器function isiterator(arr) { // 声明一个变量让它从0开始迭代 let num = 0; return { next() { var result = { value: arr[num], // 设置迭代状态 (判断是否继续) done: num >= arr.length } num++; return result; } } }
接着我们来封装个经典的斐波拉契
斐波拉契主要数据排列为:1,1,2,3,5… 即除了第一个和第二个为1以外,后面的为前两个之和function createFeiboIter() { // 定义数组初始值 let a = 1; let b = 1; // 记录当前位置 let num = 1; return { next() { let value; if (num <= 2) { value = 1; } else { value = a + b; } var res = { value, da: false // 因为斐波拉契没有极限值所以返回一直为Flase即可以持续继续 } // 初始值重新赋予 a = b; b = res.value; num++; return res; } } } var iterator = createFeiboIter(); console.log(iterator.next().value); // 1 console.log(iterator.next().value); // 1 console.log(iterator.next().value); // 2 console.log(iterator.next().value); // 3 console.log(iterator.next().value);//5
结果如图:
数组的迭代器
// 在ES6里面 对象具有知名符号Symbol.iterator这个属性,这个对象就可以进行迭代let arr = arr[Symbol.iterator]();
for of方法
数组可以直接用for of便利 普通和对象里面没有iterator接口 所以无法使用for-of进行遍历 类数组对象也可以进行遍历 对象设置迭代器var obj = { a : 1, b : 2, c : 3,//让其可以使用for of方法 [Symbol.iterator] () { // 拿到对象所有的键名 const keys = Object.keys(this); let i = 0 // 设置迭代器 return { next : () => { const propName = keys[i]; const propValue = this[propName]; var result = { value : { propName, propValue }, done : i++ >= keys.length } return result; } } } }
什么是generator函数?
是一种ES6里面提供的一种方法 他是yield标识符和next方法调用 作用是可以是函数分段调用 怎么使用生成器?function* love() { yield "1"; yield "2"; yield "3"; return "over" } var loves = love(); console.log(loves.next()); console.log(loves.next()); console.log(loves.next()); console.log(loves.next()); console.log(loves.next());
输出为:
调用next方法之后的逻辑 :
1.当函数调用next方法之后 在函数内部遇到了yield关键字 函数就会暂停执行 next方法的返回值就是yeild 后面接的数据 2.当我们再次调用next方法时 就会从当前暂停的位置继续往下走 直到遇到下一个yield 3.运行到最后 没有yield关键字 就会一直往后执行 直到遇到return 关键字 返回的是return后面的值 并且状态变成true 4.最后没有遇到return 返回值为undefined 状态值为true generator函数的特性 :var arr = [15, 16, 17, 19]; function* createGenerator(arr) { for(const item of arr) { yield item; } } const iter = createGenerator(arr); console.log(iter.next()); console.log(iter.next()); console.log(iter.next()); console.log(iter.next()); console.log(iter.next());
结果为:
下面我们在看看生成器里面调用另外一个生成器
function* f1() { yield 1; yield 2; } function* f2() { yield* f1(); // 在生成器内部调用其他的生成器 一定要在yield 后面加上* yield 4; // return 方法调用之后 就会提前结束生成器函数 整个迭代过程提前结束 // return 9; // 可以在生成器内部抛出一个错误 // throw 8; yield 5; yield 6; } const gener = f2(); console.log(gener.next()); console.log(gener.next()); console.log(gener.next()); console.log(gener.next()); console.log(gener.next()); console.log(gener.next());
结果为:
转载地址:http://xwezi.baihongyu.com/