es6 기본 Iterator 인터페이스
Iterator 인터페이스의 목적 은 모든 데이터 구 조 를 위해 통 일 된 방문 체 제 를 제공 하 는 것 이다. 즉
for...of 순환 (상세 한 것 은 다음 글 참조) 이다.for...of 순환 을 사용 하여 특정한 데이터 구 조 를 옮 겨 다 닐 때 이 순환 은 자동 으로 Iterator 인 터 페 이 스 를 찾 습 니 다.하나의 데이터 구조 가 Iterator 인 터 페 이 스 를 배치 하면 우 리 는 이러한 데이터 구 조 를 '옮 겨 다 닐 수 있 는' (iterable) 이 라 고 부른다.
ES6 는 기본 Iterator 인터페이스 가 데이터 구조의
Symbol.iterator 속성 에 배치 되 거나 하나의 데이터 구조 가 Symbol.iterator 속성 만 있 으 면 '옮 겨 다 닐 수 있 는' (iterable) 이 라 고 볼 수 있 도록 규정 하고 있다. Symbol.iterator속성 자 체 는 함수 입 니 다. 현재 데이터 구조의 기본 적 인 교체 기 생 성 함수 입 니 다. 이 함 수 를 실행 하면 교체 기 를 되 돌려 줍 니 다. 속성 명 Symbol.iterator 은 표현 식 입 니 다. Symbol 대상 의 iterator 속성 을 되 돌려 줍 니 다. 이것 은 미리 정 의 된 Symbol 형식의 특수 값 이 므 로 괄호 안에 넣 어야 합 니 다.(Symbol 1 장 참조).
const obj = {[Symbol.iterator] : function () {return {next: function () {return {value: 1,done: true};}};}};上面代码中,对象
obj是可遍历的(iterable),因为具有Symbol.iterator属性。执行这个属性,会返回一个迭代器对象。该对象的根本特征就是具有next方法。每次调用next方法,都会返回一个代表当前成员的信息对象,具有value和done两个属性。ES6 的有些数据结构原生具备 Iterator接口(比如数组),即不用任何处理,就可以被
for...of循环遍历。原因在于,这些数据结构原生部署了Symbol.iterator属性(详见下文),另外一些数据结构没有(比如对象)。凡是部署了Symbol.iterator属性的数据结构,就称为部署了迭代器接口。调用这个接口,就会返回一个迭代器对象。原生具备 Iterator接口的数据结构如下。
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
下面的例子是数组的Symbol.iterator属性。
let arr = ['a', 'b', 'c'];let iter = arr[Symbol.iterator]();iter.next() // { value: 'a', done: false }iter.next() // { value: 'b', done: false }iter.next() // { value: 'c', done: false }iter.next() // { value: undefined, done: true },
arr, ,arrSymbol.iterator。 , , 。Iterator , ,
for...of。 , ( ) Iterator ,Symbol.iterator,for...of。(Object) Iterator , , , 。 , , , , 。 , , , Map ,ES5 Map , ES6 。
for...ofIterator ,Symbol.iterator( )。
class RangeIterator {constructor(start, stop) {this.value = start;this.stop = stop;}[Symbol.iterator]() { return this; }next() {var value = this.value;if (value < this.stop) {this.value++;return {done: false, value: value};}return {done: true, value: undefined};}}function range(start, stop) {return new RangeIterator(start, stop);}for (var value of range(0, 3)) {console.log(value); // 0, 1, 2}Iterator 。
Symbol.iterator, 。。
function Obj(value) {this.value = value;this.next = null;}Obj.prototype[Symbol.iterator] = function() {var iterator = { next: next };var current = this;function next() {if (current) {var value = current.value;current = current.next;return { done: false, value: value };} else {return { done: true };}}return iterator;}var one = new Obj(1);var two = new Obj(2);var three = new Obj(3);one.next = two;two.next = three;for (var i of one){console.log(i); // 1, 2, 3}
Symbol.iterator,iterator,next, , 。Iterator 。
let obj = {data: [ 'hello', 'world' ],[Symbol.iterator]() {const self = this;let index = 0;return {next() {if (index < self.data.length) {return {value: self.data[index++],done: false};} else {return { value: undefined, done: true };}}};}};(
length), Iterator , ,Symbol.iteratorIterator 。
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];//NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];[...document.querySelectorAll('div')] //NodeList , , 。 ,
Symbol.iterator, 。
Symbol.iterator。
let iterable = {0: 'a',1: 'b',2: 'c',length: 3,[Symbol.iterator]: Array.prototype[Symbol.iterator]};for (let item of iterable) {console.log(item); // 'a', 'b', 'c'},
Symbol.iterator, 。
let iterable = {a: 'a',b: 'b',c: 'c',length: 3,[Symbol.iterator]: Array.prototype[Symbol.iterator]};for (let item of iterable) {console.log(item); // undefined, undefined, undefined}
Symbol.iterator( ), 。
var obj = {};obj[Symbol.iterator] = () => 1;[...obj] // TypeError: [] is not a function,
objSymbol.iterator, 。,
for...of( ),while。
var $iterator = ITERABLE[Symbol.iterator]();var $result = $iterator.next();while (!$result.done) {var x = $result.value;// ...$result = $iterator.next();},
ITERABLE,$iterator。 (next),done, , (next), 。