Iterator和for..of循环----ES6重刷16

概念
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制【使用for...of自动检索是否具备iterator接口,若没有则返回错误不可遍历uniterable,若检索具备iterator接口,则自动调用其内部的next()函数,因为iterator接口指向调用的是next()方法/函数,且next()返回值则是一个指针对象】

工作原理
创建一个指针对象(遍历器对象),指向数据结构的起始位置。
第一次调用next方法,指针会自动指向数据结构的第一个成员
接下来不断调用next方法,指针会一直往后移,直到指向最后一个成员
每调用next方法返回的是一个包含value和done的对象,{value:当前成员的值,done:布尔型}
*value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束
*当遍历结束的时候返回的value是undefined,done是true

模拟Iterator接口

//简单构造iterator
function makeIterator(array) {
	let index = 0;
	//返回一个对象,用于实例化new出来的对象
	return {
		//返回一个指针对象
		next: () => {
			//注意啊,三目运算符,好东西啊,可以代替繁琐的if...else啊
			return index < array.length ? {
				value: array[index++],
				done: false // 表示所遍历对象还未遍历完毕
			} : {
				value: undefined,
				done: true // 表示所遍历对象遍历结束
			}
		}
	}
}

const item = new makeIterator([1, 2]);
console.log(item.next());//Object { value: 1, done: false }
console.log(item.next());//Object { value: 2, done: false }
console.log(item.next());//Object { value: undefined, done: true }

默认接口
具有原生iterator接口的数据类型
Array
NodeList 对象
String
Map
Set
函数的 arguments 对象
TypedArray

const item1 = [1,2,3];
const divList = document.querySelectorAll('div');
const str = "abc";
const set = new Set([1,2,3]);
const map = new Map([["userName", "burningSnow"],["age",21],["gender","male"]]);
const dataType = [item1,divList,str,set,map];
function Arguments() {
	for(let i of arguments) {
		console.log(i);//1,2,3
	}
}
for(let index in dataType) {
	for (let i of dataType[index]) {
		console.log(i);
	}
}
Arguments(1,2,3);

Symbol.iterator属性
对于对象object来说是没有具体默认的iterator接口的,因为考虑到对象是多变的,然而当我们想去遍历时,那该怎末办?
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性iterator接口指向调用的是自定义的next()方法/函数】,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)Symbol.iterator属性本身是一个函数【相当于上述demo中的makeIterator函数】,就是当前数据结构默认的遍历器生成函数。
想想:我们的Symbol.iterator应该设置在哪里呢?怎末设置?
01,设置在new出来的实例本身【不建议,没有扩展性】

// 第一种方式【比较low】,Symbol.iterator属性
let obj = {
  userName: "burningSnow",
  age: "21",
  gender: "male",
  [Symbol.iterator]: () => {
    let index = 0;
    let attrList = Object.getOwnPropertyNames(obj);
    return {
      next: () => {
        return index < attrList.length ? {
          value: attrList[index++], done: false
        } : {
            value: undefined, done: true
          }
      }
    }
  }
}
for (let i of obj) {
  console.log(i);//userName,age,gender
}

// 第二种方式【结合Generator构造器】
const obj = new Proxy({
  'first': 'first',
  'second': 'second',
  'third': undefined,
}, {
  get: (target, property) => target[property] === undefined ? "暂无数据" : target[property],
})

// 布置自定义Iterator接口
Reflect.set(obj, Symbol.iterator, function* () {
  for (const key in this) { // this指代数据源obj,还可以这么玩,有意思
    yield this[key]
  }
})

console.log([...obj]) // ["first", "second", "暂无数据"]

02,设置在其隐式原型上(实例的构造函数上)【较好,不仅封装了,还可以继承】

//原型上设置
class iterator {
	//类的构造函数
	constructor(userName, age) {
		this.userName = userName;
		this.age = age;
		/**
		 * 设置Symbol属性作为index
		 * 且不会被Object.getOwnPropertyNames(this)捕获到
		 */
		this[Symbol.for("index")] = 0;
	}
	//类的一般方法,只能用简写方式,不可用function(){}或则箭头函数
	[Symbol.iterator]() {
		return this; // 返回对象本身【必须指定】
	}
	//next遍历器实现函数
	next() {
		let attrList = Object.getOwnPropertyNames(this);
		return this[Symbol.for("index")] < attrList.length ? {
			value: attrList[ this[Symbol.for("index")]++],
			done: false
		} : {
			value: undefined,
			done: true
		}
	}
}
let myIterator = new iterator("burningSnow", 21);
console.log(myIterator);
for (let i of myIterator) {
	console.log(i);
}

myIterator实例结果图
在这里插入图片描述

注意:
1、只要相关的数据结构部署了Iterator接口【无论是原生部署还是自定义部署】,就可以使用扩展运算符...for..of遍历

2、任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值