>source

이터러블이 이터레이터와 같은가요, 아니면 다른가요?

그런 것 같다. 사양에서, iterable은 객체입니다.오브제, 그렇게obj[Symbol.iterator]함수를 참조하므로 호출될 때 다음을 가진 객체를 반환합니다.다음반환할 수 있는 메서드{값: ____, 완료: __}물체:

function foo() {
    let i= 0;
    const wah= {
        next: function() {
            if (i <= 2) return { value: (1 + 2 * i++), done: false }
            else return { value: undefined, done: true }
        }
    };
    return wah;     //wah is iterator
}
let bar= {}        //bar is iterable
bar[Symbol.iterator]= foo;
console.log([...bar]);             //[1, 3, 5]
for (a of bar) console.log(a);     //1 3 5 (in three lines)

위의 code에서술집반복 가능하며는 반복자이고다음()반복자 인터페이스입니다.

따라서 iterable과 iterator는 다른 것입니다.

그러나 이제 생성기와 반복기의 일반적인 예에서:

function* gen1() {
    yield 1;
    yield 3;
    yield 5;
}
const iter1= gen1();
console.log([...iter1]);                           //[1, 3, 5]
for (a of iter1) console.log(a);                   //nothing
const iter2= gen1();
for (a of iter2) console.log(a);                   //1 3 5 (in three lines)
console.log(iter1[Symbol.iterator]()=== iter1);   //true

위의 경우,1세대는 발전기이고,반복 1는 반복자이고iter1.next()적절한 일을 할 것입니다. 하지만iter1[기호.iterator]호출될 때 반환하는 기능을 제공합니다.반복 1, 반복자입니다. 그래서반복 1이 경우 iterable과 iterator가 모두 있습니까?

게다가,반복 1예제 1의 iterable이 다음을 줄 수 있기 때문에 위의 예제 1과 다릅니다.[1, 3, 5]원하는 만큼 사용[...술집], 동안반복 1반복 가능하지만 매번 동일한 반복자 인 자체를 반환하기 때문에[1, 3, 5]한 번.

따라서 우리는 iterable에 대해 말할 수 있습니다.술집, 몇 번이나[...술집]결과를 주다[1, 3, 5]--그리고 대답은, 그것은 달려 있습니다. 그리고 iterable은 iterator와 동일합니까? 그리고 대답은 서로 다르지만 iterable이 자신을 iterator로 사용할 때 같을 수 있다는 것입니다. 그 맞습니까?

밀접하게 관련됨: Javascript iterable의 기술적 정의는 무엇입니까?

Bergi2021-11-25 10:29:35

"그래서 iter1은 이 경우 이터러블이면서 동시에 이터레이터인가요?" -예. 모든 기본 반복자는 또한 자신을 반환하여 반복 가능하므로 반복 가능을 기대하는 구문으로 쉽게 전달할 수 있습니다.

Bergi2021-11-25 10:29:35

Iterator와 Iterable의 차이점 중복 가능성

Felix Kling2021-11-25 10:29:35
  • 답변 # 1

    간단한 용어로 차이점은 다음과 같습니다.

    • 반복자-가지고 있는 모든 개체다음다음 값을 반환하는 함수
    • 반복 가능-가지고 있는 모든 개체[Symbol.iterator]반환하는 함수반복자

    그러나 두 가지를 모두 수행하는 객체가 있는 경우반복 가능한 반복자. 예를 들어, 모든 함수는 하나를 반환합니다.

    그리고 일반적인 구현반복 가능한 반복자다음과 같이 진행됩니다.

    {
        [Symbol.iterator]() {
            return this; //returning iterator
        },
        next() {
            //return next value here
        }
    } //=> IterableIterator
    

  • 답변 # 2

    용어에 대한 보다 정확한 정의가 있으며 다음과 같은 명확한 답변이 있습니다.

    및 에 따르면:

    우리는

    function* foo() {   //note the "*"
        yield 1;
        yield 3;
        yield 5;
    }
    

    생성기 함수라고 합니다. 그리고 우리가 가질 때

    let bar= foo();
    

    생성기 객체입니다. 그리고 .

    더 간단한 버전은 iterator 인터페이스입니다..다음()방법.

    반복 가능한 프로토콜은 다음과 같습니다.오브제,obj[Symbol.iterator]"반복자 프로토콜을 준수하는 객체를 반환하는 제로 인수 함수"를 제공합니다.

    에 의해 생성기 객체를 "생성기"라고 부를 수도 있는 것 같습니다.

    참고 Nicolas Zakas의 저서 ECMAScript 6의 이해, 그는 아마도 "생성기 함수"를 "생성기"로, "생성기 개체"를 "반복기"로 느슨하게 불렀을 것입니다. 요점은 둘 다 실제로 "생성기"와 관련되어 있다는 것입니다. 하나는 생성기 함수이고 다른 하나는 생성기 개체 또는 생성기입니다. 생성기 객체는 반복 가능한 프로토콜과 반복자 프로토콜을 모두 준수합니다.

    단순히 iterator프로토콜을 준수하는 객체인 경우 사용할 수 없습니다[...이터]또는~을 위해. 반복 가능한프로토콜을 준수하는 개체여야 합니다.

    그리고 도 있습니다. 다음과 같은 방법을 포함하여 더 큰 인터페이스가 있습니다.각각,지도,줄이다현재 Array 인터페이스 및 다음과 같은 새로운 인터페이스가져 가다, 그리고떨어지다. 현재 반복자는다음상호 작용.

    원래 질문에 답하기 위해: iterator와 iterable의 차이점은 무엇입니까? 대답은 다음과 같습니다. iterator는 인터페이스가 있는 객체입니다..다음(), 그리고 iterable은 객체입니다.오브제그런obj[Symbol.iterator]호출될 때 반복자를 반환하는 인수가 없는 함수를 제공할 수 있습니다.

    제너레이터는 iterable과 iterator 모두에 추가할 수 있습니다.

  • 답변 # 3

    예, iterablesiterators는 다르지만 대부분의 iterators(예:열쇠또는가치방법Array.prototype또는 생성기 함수의 생성기)에서 상속 %IteratorPrototype% 개체,Symbol.iterator다음과 같은 방법:

    [Symbol.iterator]() {
        return this;
    }
    

    결과는 모든 표준 반복자도 반복 가능하다는 것입니다. 그래서 직접 사용하거나 다음에서 사용할 수 있습니다.~의루프 등(반복자가 아닌 반복 가능을 예상함).

    고려열쇠배열 방법: 배열의 키(숫자로 인덱스)를 방문하는 배열 반복자를 반환합니다. 반복자를 반환합니다. 그러나 일반적인 용도는 다음과 같습니다.

    for (const index of someArray.keys()) {
        //...
    }
    

    for-of반복자가 아닌 반복 가능을 취하는데 왜 작동할까요?

    반복자도 반복 가능하기 때문에 작동합니다.Symbol.iterator그냥 반환이것.

    여기 내 책의 6장에서 사용한 예가 있습니다. 모든 항목을 반복하고 싶지만 첫 번째 항목은 건너뛰고 사용하지 않으려는 경우일부분부분 집합을 잘라내기 위해 반복자를 얻고 첫 번째 값을 읽은 다음~의고리:

    const a= ["one", "two", "three", "four"];
    const it= a[Symbol.iterator]();
    //Skip the first one
    it.next();
    //Loop through the rest
    for (const value of it) {
        console.log(value);
    }

    이것은 모두 표준반복자입니다. 때때로 사람들은 다음과 같이 수동으로 코딩된 반복자의 예를 보여줍니다.

    function range(start, end) {
        let value= start;
        let inc= start < end ? 1 : -1;
        return {
            next() {
                const done= value== end;
                const result= {done, value};
                if (!done) {
                    value += inc;
                }
                return result;
            }
        };
    }
    //Works when used directly
    const it= range(1, 5);
    let result;
    while (!(result= it.next()).done) {
        console.log(result.value);
    }
    //Fails when an iterable is expected
    try {
        for (const value of range(1, 5)) {
            console.log(value);
        }
    } catch (e) {
        console.error(e.message);
    }

    에 의해 반환된 반복자범위iterable이 없습니다, 그래서 우리가 그것을 사용하려고 하면 실패합니다~의.

    반복 가능하게 하려면 다음 중 하나를 수행해야 합니다.

    1. 추가Symbol.iterator위의 답변 시작 부분에 있는 메소드 또는
    2. 이미 해당 메소드가 있는 %IteratorPrototype%에서 상속하도록 합니다.

    슬프게도 TC39는 %IteratorPrototype% 개체를 가져오는 직접적인 방법을 제공하지 않기로 결정했습니다. 간접적인 방법(배열에서 반복자를 가져온 다음 %IteratorPrototype%로 정의된 프로토타입을 가져옴)이 있지만 고통스럽습니다.

    하지만 어쨌든 수동으로 반복자를 작성할 필요는 없습니다. 반환하는 생성기는 반복 가능하므로 생성기 함수를 사용하십시오.

    function* range(start, end) {
        let value= start;
        let inc= start < end ? 1 : -1;
        while (value !== end) {
            yield value;
            value += inc;
        }
    }
    //Works when used directly
    const it= range(1, 5);
    let result;
    while (!(result= it.next()).done) {
        console.log(result.value);
    }
    //Also works when an iterable is expected
    for (const value of range(1, 5)) {
        console.log(value);
    }


    반대로 모든 이터러블이 이터레이터는 아닙니다. 배열은 반복 가능하지만 반복자는 아닙니다. 문자열, 지도 및 집합도 마찬가지입니다.

  • 이전 네트워크 이미지에서 작동하지 않는 try/catch(예외: 잘못된 이미지 데이터)
  • 다음 c# : try/catch 블록 내에 채워진 ViewBag 문자열을 인쇄하는 방법