>  기사  >  웹 프론트엔드  >  JavaScript의 반복 가능한 객체와 반복자를 알고 있나요?

JavaScript의 반복 가능한 객체와 반복자를 알고 있나요?

醉折花枝作酒筹
醉折花枝作酒筹앞으로
2021-08-09 17:53:542658검색

Iteration은 컬렉션 요소에 액세스하는 방법입니다. 반복 가능한 개체라고 합니다. 반복자 개체는 탐색 위치를 기억할 수 있는 개체입니다. , 반복자는 앞으로만 이동할 수 있고 뒤로는 이동할 수 없습니다.

지연 평가

지연 평가는 종종 "지연 평가" 또는 "지연 평가"로 번역됩니다. 이는 실제로 실행이 필요한 경우에만 표현식의 값을 계산하는 것을 의미합니다.

게으른 평가의 반대는 초기 평가입니다. 탐욕적 평가 또는 엄격한 평가라고도 알려진 초기 평가는 대부분의 전통적인 프로그래밍 언어의 평가 전략입니다.

지연 평가의 특성을 최대한 활용함으로써 얻을 수 있는 이점은 주로 다음 두 가지 측면에 반영됩니다.

  • 불필요한 계산을 피하고 성능을 향상시킵니다.

  • 공간을 절약하고 무한 루프 데이터 구조를 가능하게 만듭니다.

Iterators

ES6의 Iterator를 사용하면 사용자 정의 데이터 시퀀스를 느리게 평가하고 생성할 수 있습니다. 반복은 데이터를 순회하는 메커니즘입니다. 반복자는 데이터 구조(Iterable이라고 함)의 요소를 순회하는 데 사용되는 포인터이자 값 시퀀스를 생성하는 데 사용되는 포인터입니다.

반복자는 반복할 수 있는 객체입니다. 반복 가능한 객체처럼 동작하도록 데이터 컨테이너를 추상화합니다.

Iterator는 인스턴스화될 때 각 항목의 값을 계산하지 않으며 요청 시 다음 값만 생성합니다. 이는 특히 대규모 데이터 세트나 무한 요소 시퀀스의 경우 매우 유용합니다.

Iterable 객체

Iterable 객체는 해당 요소를 공개적으로 액세스할 수 있도록 하는 데이터 구조입니다. JS의 많은 객체는 반복 가능하므로 감지하기 쉽지 않을 수 있지만 주의 깊게 살펴보면 반복의 특징을 찾을 수 있습니다.

  • new Map([iterable])

  • new WeakMap([ iterable] ) [new set ([iterable])

  • new weepset ([iterable])

  • promise.all ([[iterable]))

  • promise.race ([iterable])

  • Array.from([iterable])
  • 에는 반복 가능한 객체도 필요합니다. 그렇지 않으면 유형 오류가 발생합니다. 예:

    for ... of
  • . )
  • const [a, b, ..] = iterable(구조 분해 할당)


  • yield*(생성기)
  • JavaScript에는 반복 가능한 항목이 내장되어 있습니다:

String,Array,TypedArray,Map ,세트.

Iteration 프로토콜

Iterator와 Iterable 객체는 반복 프로토콜을 따릅니다.

프로토콜은 인터페이스 세트이며 이를 사용하는 방법을 지정합니다.

Iterator는 Iterator 프로토콜을 따르고, Iterable은 Iterable 프로토콜을 따릅니다.

Iterable 프로토콜

객체를 반복 가능하게 만들려면 반복자의 팩토리인 Symbol.iterator를 통해 반복자 메서드를 구현해야 합니다.

TypeScript를 사용하면 반복 가능한 프로토콜은 다음과 같습니다.

interface Iterable {
  [Symbol.iterator]() : Iterator;
}

Symbol.iterator]()는 매개변수가 없는 함수입니다. 반복 가능한 객체에서 이를 호출한다는 것은 이를 통해 반복 가능한 객체(일반 함수 또는 생성기 함수일 수 있음)에 액세스할 수 있음을 의미합니다.

Iterator 프로토콜

반복자 프로토콜은 일련의 값을 생성하는 표준 방법을 정의합니다.

객체가 반복자가 되려면 next() 메서드를 구현해야 합니다. 반복자는 return() 메서드를 구현할 수 있으며 이에 대해서는 이 문서의 뒷부분에서 설명합니다.

TypeScript를 사용하면 반복자 프로토콜은 다음과 같습니다.

interface Iterator {
    next() : IteratorResult;
    return?(value?: any): IteratorResult;
}

IteratorResult는 다음과 같이 정의됩니다.

interface IteratorResult {
    value?: any;
    done: boolean;
}

    done은 반복자가 사용되었는지 소비자에게 알리고, false는 아직 생성할 값이 있음을 의미하고, true는 의미합니다. 반복자가 종료되었습니다.
  • 값은 JS 값일 수 있으며 소비자에게 표시되는 값입니다.
  • done이 true인 경우 값을 생략할 수 있습니다.

combination

Iterator와 Iterable 객체는 다음 그림으로 표현할 수 있습니다.

JavaScript의 반복 가능한 객체와 반복자를 알고 있나요?Examples

기본 지식을 소개한 후 몇 가지 예를 사용하여 이미지를 심화해 보겠습니다.

Range Iterator

아주 기본적인 반복자인 createRangeIterator 반복자부터 시작해 보겠습니다.

다음 IteratorResult를 얻기 위해 수동으로 it.next()를 호출합니다. 마지막 호출은 {done: true}를 반환합니다. 이는 이제 반복자가 사용되고 더 이상 값을 생성하지 않음을 의미합니다.

function createRangeIterator(from, to) {
  let i = from;

  return {
    next() {
      if (i <= to) {
        return { value: i++, done: false };
      } else {
        return { done: true };
      }
    }
  }
}

const it = createRangeIterator(1, 3);

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

JavaScript의 반복 가능한 객체와 반복자를 알고 있나요?

Iterable Range Iterator

이 글의 앞부분에서 JS의 특정 문에는 반복 가능한 개체가 필요하다고 언급했습니다. 따라서 이전 예제는 for...of 루프와 함께 사용하면 작동하지 않습니다.

하지만 반복자와 반복 가능한 프로토콜을 준수하는 객체를 만드는 것은 매우 쉽습니다.

function createRangeIterator (from, to) {
  let i = from

  return {
    [Symbol.iterator] () {
      return this
    },
    next() {
      if (i <= to) {
        return { value: i++, done: false }
      } else {
        return { done: true }
      }
    }
  }
}

const it = createRangeIterator(1, 3)

for (const i of it) {
  console.log(i)
}

无限序列迭代器

迭代器可以表示无限制大小的序列,因为它们仅在需要时才计算值。

注意不要在无限迭代器上使用扩展运算符(...),JS 将尝试消费迭代器,由于迭代器是无限的,因此它将永远不会结束。 所以你的应用程序将崩溃,因为内存已被耗尽 

同样,for ... of 循环也是一样的情况,所以要确保能退出循环:

function createEvenNumbersIterator () {
  let value = 0

  return {
    [Symbol.iterator] () {
      return this
    },
    next () {
      value += 2
      return { value, done: false}
    }
  }
}

const it = createEvenNumbersIterator()

const [a, b, c] = it
console.log({a, b, c})

const [x, y, z] = it
console.log({ x, y, z })

for (const even of it) {
  console.log(even)
  if (even > 20) {
    break
  }
}

JavaScript의 반복 가능한 객체와 반복자를 알고 있나요?

关闭迭代器

前面我们提到过,迭代器可以有选择地使用return()方法。 当迭代器直到最后都没有迭代时使用此方法,并让迭代器进行清理。

for ... of循环可以通过以下方式更早地终止迭代:

  • break

  • continue

  • throw

  • return

function createCloseableIterator () {
  let idx = 0
  const data = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;]

  function cleanup() {
    console.log(&#39;Performing cleanup&#39;)
  }
  return {
    [Symbol.iterator]() { return this },
    next () {
      if (idx <= data.length - 1) {
        return { value: data[idx++], done: false }
      } else {
        cleanup()
        return { done: true }
      }
    },
    return () {
      cleanup()
      return { done: true }
    }
  }
}

const it = createCloseableIterator()

for (const value of it) {
  console.log(value)
  if (value === &#39;c&#39;) {
    break
  }
}

console.log(&#39;\n----------\n&#39;)

const _it = createCloseableIterator();
for (const value of _it) {
  console.log(value);
}

JavaScript의 반복 가능한 객체와 반복자를 알고 있나요?

  • 如果知道迭代器已经结束,则手动调用cleanup()函数。

  • 如果突然完成,则return()起作用并为我们进行清理。

【推荐学习:javascript高级教程

위 내용은 JavaScript의 반복 가능한 객체와 반복자를 알고 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제