前端进阶攻略之迭代器
前端进阶攻略之迭代器
前端进阶攻略之迭代器
一.什么是迭代器?
1.什么是迭代?
从一个数据集合中按照一定的顺序,不断的取出数据的过程
2.迭代和遍历的区别?
迭代强调的依次取出,不能确定可以取出的值有多少,也不能保证去把数据全部取完
遍历必须保证数据的长度,循环不断的全部取出,针对于数据量过大的情况下使用遍历,需要时间过长
3.迭代器
对迭代过程的封装,通常表现为对象的数据形式(也可以使用数组),不同语言中,表现出了的迭代形式不一样
4.迭代模式
一种编程设计模式,用于同一迭代的过程,并且规范迭代器的格式
二.JS原生迭代器
在写原生迭代器时,首先要明白迭代器的原理
迭代器需要满足的条件:
2.1.取出下一个数据的能力
2.2.判断是否有下一个数据
function iterator(arr){
return{
i:0,
next(){
var result={
value:arr[this.i],
done:this.i>=arr.length
}
this.i++;
return result;
}
}
}
var arr1=[1,2,3,4,5,6];
let it=iterator(arr1);
只要知道迭代器需要满足的条件,写一个原生迭代器还是非常简单的
最终在控制台中调用.next()方法输出的结果为:
如果用while()循环可以让迭代器自己取数据,直到没有数据为止
const arr = [1,2,3,4,5]
const iterator ={ //用于迭代数组的对象,iterator为迭代器的名称
i : 0,
next(){
var result = {
value : arr[this.i],
done : this.i >= arr.length
}
this.i ++;
return result;
}
}
console.log(iterator)
// 让迭代器自己取数据,直到没有数据为止
let data = iterator.next();
while(!data.done){
console.log(data.value)
data = iterator.next();
}
console.log("迭代完成");
三.ES6中的迭代器
在es6中如果对象具有知名符号属性Symbol.iterator,则表示该对象可以迭代
const arr = [464, 878, 88, 22, 45, 4, 8, 7]
// // 在es6中如果对象具有知名符号属性Symbol.iterator,则表示该对象可以迭代
console.log(arr)
const iterator = arr[Symbol.iterator](); //es6之后,数组可以直接创建迭代对象
console.log(iterator.next()); //{value: 464, done: false}
console.log(iterator.next()); //{value: 878, done: false}
console.log(iterator.next()); //{value: 88, done: false}
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
使用es6中的知名符号Symbol.iterator可以直接创建一个迭代对象,通过调用迭代对象的next()方法,可以直接迭代数组中的数据
3.1、使用迭代器生成斐波那契数列
下面我们就使用迭代器来自定义自己的一个斐波那契数列组,我们直到斐波那契数列有两个运行前提,第一个前提是初始化的前两个数字为0,1,第二个前提是将来的每一个值都是前两个值的和。这样我们的目标就是每次都迭代输出一个新的值。
<!-- 1 1 2 3 5 8 13..... -->
<!-- 创建一个分斐波那契数列的迭代器 -->
function createFeibo(){
let prev1 = 1;
let prev2 = 1; //前两位
let n = 1;//当前第几位
return {
next(){
let value;
if(n <=2 ){
value = 1
}else{
value = prev1 + prev2;
}
const result = {
value,
done: false
}
prev2 = prev1;
prev1 = result.value;
n++;
return result
}
}
}
const iter = createFeibo()
在 ES6 中常用的集合对象(数组、Set/Map集合)和字符串都是可迭代对象,这些对象都有默认的迭代器和Symbol.iterator属性。
通过生成器创建的迭代器也是可迭代对象,因为生成器默认会为Symbol.iterator属性赋值。
四. for of循环
for of 循环遍历、 就是专门针对可迭代对象的, 不是可迭代对象不能使用 forof循环。
const arr1 = [1, 2, 3, 4, 5, 6, 7];
for (let item of arr1) {
console.log(item)
}
for of与for in 区别:
区别①:for of无法循环遍历对象
var userMsg = {
0: 'nick',
1: 'freddy',
2: 'mike',
3: 'james'
};
for(var key in userMsg){
console.log(key, userMsg[key]);
}
console.log('-----------分割线-----------');
for(var item of userMsg){
console.log(item);
区别②:遍历输出结果不同
var arr = ['nick','freddy','mike','james'];
for(var key in arr){
console.log(key);
}
console.log('-----------分割线-----------');
for(var item of arr){
console.log(item);
}
不难看出,for in循环遍历的是数组的键值(索引),而for of循环遍历的是数组的值。
区别③:for in 会遍历自定义属性,for of不会
var arr = ['nick','freddy','mike','james'];
arr.name = "数组";
for(var key in arr){
console.log(key+': '+arr[key]);
}
console.log('-----------分割线-----------');
for(var item of arr){
console.log(item);
给数组添加一个自定义属性name,并且赋值"数组"。然后进行遍历输出的,会发现新定义的属性也被for in输出来了,而for of并不会对name进行输出。