>  기사  >  웹 프론트엔드  >  JavaScript ES6의 반복자와 생성기 소개

JavaScript ES6의 반복자와 생성기 소개

巴扎黑
巴扎黑원래의
2017-08-21 09:44:201088검색

이 글은 주로 ES6 Iterator와 Generator에 대한 심층적인 이해를 소개하는 글입니다. 편집자는 꽤 좋다고 생각해서 지금 공유하고 참고용으로 제공하겠습니다. 편집자를 따라가서 살펴보겠습니다

이 글에서는 ES6 반복자와 생성기에 대한 심층적인 이해를 소개하고 자세한 내용을 공유합니다.

루프 문 관련 문제


var colors = ["red", "green", "blue"];
for(var i=0; i<colors.length; i++){
  console.log(colors[i]);
}

ES6 이전에는 이 for 루프 표준이 변수를 통해 배열 인덱스를 추적했습니다. 여러 루프가 중첩되면 여러 변수를 추적해야 하며 코드 복잡도가 크게 증가하고 루프 변수를 잘못 사용하는 버그가 쉽게 발생합니다.

이러한 복잡성을 제거하고 루프의 오류를 줄이기 위해 Iterator가 도입되었습니다.

반복자는 무엇입니까

먼저 ES5 구문을 사용하여 반복자 생성을 시뮬레이션해 보겠습니다.


function createIterator(items) {
  var i = 0;
  
  return { // 返回一个迭代器对象
    next: function() { // 迭代器对象一定有个next()方法
      var done = (i >= items.length);
      var value = !done ? items[i++] : undefined;
      
      return { // next()方法返回结果对象
        value: value,
        done: done
      };
    }
  };
}

var iterator = createIterator([1, 2, 3]);

console.log(iterator.next()); // "{ value: 1, done: false}"
console.log(iterator.next()); // "{ value: 2, done: false}"
console.log(iterator.next()); // "{ value: 3, done: false}"
console.log(iterator.next()); // "{ value: undefiend, done: true}"
// 之后所有的调用都会返回相同内容
console.log(iterator.next()); // "{ value: undefiend, done: true}"

위에서 createIterator() 함수를 호출하여 객체를 반환하고 이 객체에는 next() 메소드는 next() 메소드가 호출되면 {value: 1, done: false} 형식의 결과 객체를 반환합니다.

따라서 다음과 같이 정의할 수 있습니다. 반복자는 next() 메서드가 있는 특수 개체이며 next()가 호출될 때마다 결과 개체가 반환됩니다.

이 반복자 객체의 도움으로 처음에 표준 for 루프를 변형할 것입니다. [지금은 ES6의 새로운 for-of 루프 기능은 잊어버리세요]:


var colors = ["red", "green", "blue"];
var iterator = createIterator(colors);
while(!iterator.next().done){
  console.log(iterator.next().value);
}

뭐라고요? 루프변수라 고생이 너무 많은데, 코드상으로는 손실을 볼 가치가 있지 않나요?

그렇지 않습니다. createIterator()는 한 번만 작성하면 되며 항상 재사용할 수 있습니다. 그러나 ES6에는 반복자를 생성하는 프로세스를 더 쉽게 만들 수 있는 생성기 객체가 도입되었습니다.

생성기란 무엇인가요

생성기는 반복자를 반환하는 함수입니다. 함수 키워드 뒤에 별표(*)가 표시됩니다.


function *createIterator(items) {
  for(let i=0; i<items.length; i++) {
    yield items[i];
  }
}

let iterator = createIterator([1, 2, 3]);

// 既然生成器返回的是迭代器,自然就可以调用迭代器的next()方法
console.log(iterator.next()); // "{ value: 1, done: false}"
console.log(iterator.next()); // "{ value: 2, done: false}"
console.log(iterator.next()); // "{ value: 3, done: false}"
console.log(iterator.next()); // "{ value: undefiend, done: true}"
// 之后所有的调用都会返回相同内容
console.log(iterator.next()); // "{ value: undefiend, done: true}"

위에서는 ES6 세대를 사용하여 반복자 생성 프로세스를 크게 단순화했습니다. 항목 배열을 생성기 함수 createIterator()에 전달합니다. 함수 내에서 for 루프는 배열에서 새 요소를 지속적으로 생성하고 이를 반복자에 넣습니다. next를 호출할 때마다 루프가 중지됩니다. iterator() 메서드의 경우 루프는 계속 실행되고 다음 항복 문에서 중지됩니다.

생성기를 만드는 방법

생성기는 함수입니다:


function *createIterator(items) { ... }

는 함수 표현 모드로 작성할 수 있습니다:


let createIterator = function *(item) { ... }

은 객체에 추가할 수도 있습니다. ES5 스타일 객체 리터럴 :


let o = {
  createIterator: function *(items) { ... }
};

let iterator = o.createIterator([1, 2, 3]);

ES6 스타일 객체 메서드 약어:


let o = {
  *createIterator(items) { ... }
};

let iterator = o.createIterator([1, 2, 3]);

Iterable 객체

ES6에서는 모든 컬렉션 객체(배열, Set 컬렉션, 맵 컬렉션)와 문자열이 Iterable 객체이고, Iterable 객체는 기본 반복자에 바인딩됩니다.

오랫동안 기다려온 새로운 ES6 루프 기능인 for-of:


var colors = ["red", "green", "blue"];
for(let color of colors){
  console.log(color);
}

for-of 루프는 반복 가능한 객체에 적용할 수 있고 반복 가능한 객체 장치의 기본 반복을 활용합니다. 일반적인 프로세스는 다음과 같습니다. for-of 루프가 실행될 때마다 반복 가능한 객체의 next() 메서드를 호출하고 반복자가 반환한 결과 객체의 값 속성을 변수에 저장합니다. 루프는 계속 실행됩니다. 완료 개체가 반환될 때까지 이 프로세스를 수행합니다. 속성의 값은 true입니다.

배열이나 컬렉션의 값만 반복해야 한다면 for 루프 대신 for-of 루프를 사용하는 것이 좋은 선택입니다.

기본 반복자 액세스

Iterable 개체에는 for-of 루프 중에 색상 배열의 Symbol.iterator 메서드를 호출하여 기본 반복자를 얻습니다. 이 프로세스는 JavaScript 엔진입니다. 뒤에서 이루어졌습니다.

우리는 이 기본 반복자가 그것을 느낄 수 있도록 주도권을 잡을 수 있습니다:


let values = [1, 2, 3];
let iterator = values[Symbol.iterator]();

console.log(iterator.next()); // "{ value: 1, done: false}"
console.log(iterator.next()); // "{ value: 2, done: false}"
console.log(iterator.next()); // "{ value: 3, done: false}"
console.log(iterator.next()); // "{ value: undefined, done: true}"

이 코드에서 배열 값의 기본 반복자는 Symbol.iterator를 통해 얻어지며, 정렬. JavaScript 엔진에서 for-of 루프 문을 실행하는 것도 비슷한 프로세스입니다.

Symbol.iterator 속성을 사용하여 객체가 반복 가능한 객체인지 감지합니다.


function isIterator(object) {
  return typeof object[Symbol.iterator] === "function";
}

console.log(isIterable([1, 2, 3])); // true
console.log(isIterable(new Set())); // true
console.log(isIterable(new Map())); // true
console.log(isIterable("Hello")); // true

반복 가능한 객체 만들기

객체를 생성할 때 Symbol.iterator 속성에 생성기를 추가한 다음 이를 반복 가능한 객체로 바꿀 수 있습니다:


let collection = {
  items: [],
  *[Symbol.iterator]() { // 将生成器赋值给对象的Symbol.iterator属性来创建默认的迭代器
    for(let item of this.items) {
      yield item;
    }
  }
};

collection.items.push(1);
collection.items.push(2);
collection.items.push(3);

for(let x of collection) {
  console.log(x);
}

내장 반복자

ES6의 컬렉션 객체, 배열, Set 컬렉션 및 Map 컬렉션에는 모두 3개의 내장 반복자가 있습니다.

  • 항목 () 값이 여러 키-값 쌍인 반복자를 반환합니다. 배열인 경우 첫 번째 요소는 인덱스 위치이고, Set인 경우 첫 번째 요소와 두 번째 요소는 모두 값입니다.

  • values()는 값이 컬렉션의 값인 반복자를 반환합니다.

  • keys()는 컬렉션의 모든 키 이름을 값으로 가지는 반복자를 반환합니다. 배열이면 인덱스가 반환되고, Set이면 값이 반환됩니다(Set의 값은 키와 값으로 모두 사용됩니다).

不同集合的默认迭代器

每个集合类型都有一个默认的迭代器,在for-of循环中,如果没有显式指定则使用默认的迭代器。按常规使用习惯,我们很容易猜到,数组和Set集合的默认迭代器是values(),Map集合的默认迭代器是entries()。

请看以下示例:


let colors = [ "red", "green", "blue"];
let tracking = new Set([1234, 5678, 9012]);
let data = new Map();

data.set("title", "Understanding ECMAScript 6");
data.set("format", "print");

// 与调用colors.values()方法相同
for(let value of colors) {
  console.log(value);
}

// 与调用tracking.values()方法相同
for(let num of tracking) {
  console.log(num);
}

// 与调用data.entries()方法相同
for(let entry of data) {
  console.log(entry);
}

这段代码会输入以下内容:

"red"
"green"
"blue"
1234
5678
9012
["title", "Understanding ECMAScript 6"]
["format", "print"]

for-of循环配合解构特性,操纵数据会更方便:


for(let [key, value] of data) {
  console.log(key + "=" + value);
}

展开运算符操纵可迭代对象


let set = new Set([1, 2, 3, 4, 5]),
  array = [...set];
  
console.log(array); // [1,2,3,4,5]

展开运算符可以操作所有的可迭代对象,并根据默认迭代器来选取要引用的值,从迭代器读取所有值。然后按返回顺序将它们依次插入到数组中。因此如果想将可迭代对象转换为数组,用展开运算符是最简单的方法。

위 내용은 JavaScript ES6의 반복자와 생성기 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.