>웹 프론트엔드 >JS 튜토리얼 >ES6의 반복자와 반복 가능한 객체의 원리 소개(예제 포함)

ES6의 반복자와 반복 가능한 객체의 원리 소개(예제 포함)

不言
不言앞으로
2018-10-29 15:34:362660검색

이 글은 ES6의 반복자와 반복 가능한 객체의 원리를 소개합니다(예제 포함). 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

ES6 새로운 배열 메소드, 컬렉션, for-of 루프, 확산 연산자(...) 및 심지어 비동기 프로그래밍도 모두 반복자(Iterator) 구현에 의존합니다. 이 글에서는 ES6의 반복자와 생성기에 대해 자세히 설명하고 반복 가능한 객체의 내부 원리와 사용법을 더 자세히 살펴보겠습니다.

1. 반복자의 원리

프로그래밍 언어에서 배열이나 컬렉션을 처리할 때 루프 문을 초기화해야 합니다. 변수는 반복 위치를 기록하며, 반복기를 프로그래밍 방식으로 사용하면 이 데이터 작업을 단순화할 수 있습니다.

반복기를 디자인하는 방법은 무엇인가요?

반복자 자체는 객체입니다. 이 객체에는 결과 객체를 반환하는 next() 메서드가 있습니다. 이 결과 객체에는 다음 반환 값과 반복 완료 부울 값이 있습니다.

function createIterator(iterms) {
  let i = 0
  return {
    next() {
      let done = (i >= iterms.length)
      let value = !done ? iterms[i++] : undefined
      return {
        done,
        value
      }
    }
  }
}

let arrayIterator = createIterator([1, 2, 3])

console.log(arrayIterator.next()) // { done: false, value: 1 }
console.log(arrayIterator.next()) // { done: false, value: 2 }
console.log(arrayIterator.next()) // { done: false, value: 3 }
console.log(arrayIterator.next()) // { done: true, value: undefined }
위의 내용에 대해 구문이 헷갈린다면 다음을 참조하세요. ES6의 새로운 함수 및 객체의 구조 분해 할당에 대한 자세한 설명(코드 예)

반복자의 next()가 호출될 때마다 다음 데이터 세트가 소진될 때까지 객체가 반환됩니다.

ES6에서 반복자를 작성하는 규칙은 비슷하지만 반복자 객체를 더 쉽게 생성할 수 있도록 생성기 객체가 도입되었습니다.

2. 반복자 생성

ES6은 반복자를 생성하기 위해 생성기를 캡슐화합니다. 분명히 생성기는 함수 뒤에 별표(*)로 표시되는 반복자를 반환하는 함수이며, 새로운 내부 특수 키워드인 Yield를 사용하여 반복자의 next() 메서드 반환 값을 지정합니다.

ES6 생성기를 사용하여 반복자를 만드는 방법은 무엇입니까? 간단한 예는 다음과 같습니다.

function *createIterator() {
  yield 123;
  yield 'someValue'
}

let someIterator = createIterator()

console.log(someIterator.next()) // { value: 123, done: false }
console.log(someIterator.next()) // { value: 'someValue', done: false }
console.log(someIterator.next()) // { value: undefined, done: true }

yield 키워드를 사용하여 값이나 표현식을 반환하고 반복자에 요소를 일괄적으로 추가할 수 있습니다.

// let createIterator = function *(items) { // 生成器函数表达式
function *createIterator(items) {
  for (let i = 0; i < items.length; i++) {
    yield items[i]
  }
}

let someIterator = createIterator([123, &#39;someValue&#39;])

console.log(someIterator.next()) // { value: 123, done: false }
console.log(someIterator.next()) // { value: &#39;someValue&#39;, done: false }
console.log(someIterator.next()) // { value: undefined, done: true }

생성기 자체가 함수이므로 객체에 추가할 수 있습니다.

let obj = {
  // createIterator: function *(items) { // ES5
  *createIterator(items) { // ES6
    for (let i = 0; i < items.length; i++) {
      yield items[i]
    }
  }
}
let someIterator = obj.createIterator([123, &#39;someValue&#39;])
생성기 함수의 특징 중 하나는 Yield 문을 실행한 후 함수가 자동으로 실행을 중지하고, 다음 Yield 문을 계속 실행하기 위해 Iterator의 next() 메서드를 다시 호출한다는 것입니다.
함수 실행을 자동으로 종료하는 이 기능은 다양한 고급 용도로 활용됩니다.

3. 반복 가능한 객체

ES6에서 일반적으로 사용되는 컬렉션 객체(배열, Set/Map 컬렉션)와 문자열은 반복 가능한 객체이며 이러한 객체에는 기본 반복자와 Symbol.iterator 속성이 있습니다.

생성기를 통해 생성된 Iterator는 반복 가능한 객체이기도 합니다. 왜냐하면 생성기는 기본적으로 Symbol.iterator 속성에 값을 할당하기 때문입니다.

3.1 Symbol.iterator

Iterable 객체에는 Symbol.iterator 속성이 있습니다. 즉, Symbol.iterator 속성이 있는 객체에는 기본 반복자가 있습니다.

Symbol.iterator를 사용하여 예를 들어 배열의 경우 객체의 기본 반복자에 액세스할 수 있습니다.

let list = [11, 22, 33]
let iterator = list[Symbol.iterator]()
console.log(iterator.next()) // { value: 11, done: false }

Symbol.iterator는 배열의 반복 가능한 객체의 기본 반복자를 가져오고 이를 작동하여 배열의 요소를 순회합니다. 정렬.

반대로, 우리는 Symbol.iterator를 사용하여 객체가 반복 가능한 객체인지 여부를 감지할 수 있습니다:

function isIterator(obj) {
  return typeof obj[Symbol.iterator] === &#39;function&#39;
}

console.log(isIterator([11, 22, 33])) // true
console.log(isIterator(&#39;sometring&#39;)) // true
console.log(isIterator(new Map())) // true
console.log(isIterator(new Set())) // true
console.log(isIterator(new WeakMap())) // false
console.log(isIterator(new WeakSet())) // false

분명히 배열, Set/Map 컬렉션 및 문자열은 모두 반복 가능한 객체이지만 WeakSet/WeakMap 컬렉션(약한 참조 컬렉션) 반복적이지 않습니다.

3.2 반복 가능한 객체 만들기

기본적으로 사용자 정의 객체는 반복 가능하지 않습니다.

지금 언급한 것처럼 생성기가 생성한 반복자는 기본적으로 Symbol.iterator 속성에 값을 할당합니다.

그렇다면 사용자 정의 객체를 반복 가능한 객체로 바꾸는 방법은 무엇일까요? Symbol.iterator 속성에 생성기를 추가하면:

let collection = {
  items: [11,22,33],
  *[Symbol.iterator]() {
    for (let item of this.items){
      yield item
    }
  }
}

console.log(isIterator(collection)) // true

for (let item of collection){
  console.log(item) // 11 22 33
}

배열 항목은 반복 가능한 객체이고, 컬렉션 객체도 Symbol.iterator 속성에 값을 할당하여 반복 가능한 객체가 됩니다.

3.3 for-of

마지막 밤나무는 for-of 대신 for-of를 사용하는데 이는 반복 가능한 객체를 위해 ES6에 추가된 새로운 기능입니다.

for-of 루프의 구현 원리를 생각해 보세요.

for-of를 사용하는 반복 가능한 객체의 경우 for-of가 실행될 때마다 반복 가능한 객체의 next()가 호출되고 반환 결과가 변수에 저장되며 의 done 속성 값까지 실행이 계속됩니다. 반복 가능한 객체가 false입니다.

// 迭代一个字符串
let str = &#39;somestring&#39;

for (let item of str){
  console.log(item) // s o m e s t r i n g
}

기본적으로 for-of는 str 문자열의 Symbol.iterator 속성 메서드를 호출하여 반복자를 얻은 다음(이 프로세스는 JS 엔진에서 완료됨) next() 메서드를 여러 번 호출하여 객체 값 값을 저장합니다. 항목 변수에 있습니다.

반복할 수 없는 객체에 for-of를 사용하면 null 또는 정의되지 않음으로 인해 오류가 발생합니다!

3.4 스프레드 연산자(...)

ES6 구문 설탕 스프레드 연산자(...)는 반복 가능한 객체도 제공합니다. 즉, 배열, 집합, 문자열 및 사용자 정의 반복 가능한 객체만 "확장"할 수 있습니다.

다음 예제는 다양한 반복 가능한 객체 확장 연산자로 계산된 결과를 출력합니다.

let str = &#39;somestring&#39;
console.log(...str) // s o m e s t r i n g
let set = new Set([1, 2, 2, 5, 8, 8, 8, 9])
console.log(set) // Set { 1, 2, 5, 8, 9 }
console.log(...set) // 1 2 5 8 9
let map = new Map([[&#39;name&#39;, &#39;jenny&#39;], [&#39;id&#39;, 123]])
console.log(map) // Map { &#39;name&#39; => 'jenny', 'id' => 123 }
console.log(...map) // [ 'name', 'jenny' ] [ 'id', 123 ]
let num1 = [1, 2, 3], num2 = [7, 8, 9]
console.log([...num1, ...num2]) // [ 1, 2, 3, 7, 8, 9 ]
let udf
console.log(...udf) // TypeError: undefined is not iterable

위 코드에서 볼 수 있듯이 확장 연산자(...)는 반복 가능한 객체를 배열로 편리하게 변환할 수 있습니다. for-of와 마찬가지로 확산 연산자(...)는 반복 불가능한 개체, null 또는 정의되지 않은 개체에 사용될 때 오류를 보고합니다!

4. 기본 반복자

ES6 为很多内置对象提供了默认的迭代器,只有当内建的迭代器不能满足需求时才自己创建迭代器。

ES6 的 三个集合对象:Set、Map、Array 都有默认的迭代器,常用的如values()方法、entries()方法都返回一个迭代器,其值区别如下:

entries():多个键值对

values():集合的值

keys():集合的键

调用以上方法都可以得到集合的迭代器,并使用for-of循环,示例如下:

/******** Map ***********/
let map = new Map([['name', 'jenny'], ['id', 123]])

for(let item of map.entries()){
  console.log(item) // [ 'name', 'jenny' ]  [ 'id', 123 ]
}
for(let item of map.keys()){
  console.log(item) // name id
}
for (let item of map.values()) {
  console.log(item) // jenny 123
}

/******** Set ***********/
let set = new Set([1, 4, 4, 5, 5, 5, 6, 6,])

for(let item of set.entries()){
  console.log(item) // [ 1, 1 ] [ 4, 4 ] [ 5, 5 ] [ 6, 6 ]
}

/********* Array **********/
let array = [11, 22, 33]

for(let item of array.entries()){
  console.log(item) // [ 0, 11 ] [ 1, 22 ] [ 2, 33 ]
}

此外 String 和 NodeList 类型都有默认的迭代器,虽然没有提供其它的方法,但可以用for-of循环

위 내용은 ES6의 반복자와 반복 가능한 객체의 원리 소개(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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