컬렉션에서 각 항목을 처리하는 것은 매우 일반적인 작업입니다. JavaScript는 각 루프에 대해 간단하고 각 루프에서 map (), filter () 및 배열 포괄적 (배열 파생)에 대해 컬렉션을 반복 할 수있는 여러 가지 방법을 제공합니다. JavaScript 1.7에서 반복자와 발전기는 핵심 JavaScript 구문에 새로운 반복 메커니즘을 가져오고 각 루프 내에서의 동작을 사용자 정의하는 메커니즘을 제공합니다.
반복자
반복자는 매번 컬렉션 시퀀스에서 요소에 액세스하고 해당 순서에서 반복의 현재 위치를 추적하는 객체입니다. JavaScript 반복자는 다음 () 메소드를 제공하는 객체이며, 이는 순서에서 다음 요소를 반환합니다. 이 메소드는 순서의 모든 요소가 통과 할 때 중지 예외를 던집니다.
반복자 객체가 생성되면 다음 ()을 명시 적으로 반복하거나 각 루프에…
객체와 어레이를 반복하는 간단한 반복기는 iterator ()를 사용하여 만들 수 있습니다.
코드 사본은 다음과 같습니다.
var lang = {name : 'javaScript', BirthdayYear : 1995};
var it = iterator (lang);
초기화가 완료되면 다음 () 메소드를 호출하여 개체의 키 값 쌍에 액세스 할 수 있습니다.
코드 사본은 다음과 같습니다.
var pair = it.next (); // 키 값 쌍은 [ "이름", "JavaScript"]입니다.
pair = it.next (); // 키-값 쌍은 [ "생일", 1995]입니다.
pair = it.next (); //`stopiteration '예외가 발생했습니다
for… in loop을 사용하여 명시 적 호출을 다음 () 메소드로 바꿀 수 있습니다. StopEration 예외가 발생하면 루프가 자동으로 종료됩니다.
코드 사본은 다음과 같습니다.
var it = iterator (lang);
for (var 쌍)
인쇄 (쌍); // 하나의 [키, 값] 키-값 쌍은 매번 출력됩니다.
객체의 키 값을 반복하려면 두 번째 매개 변수를 iterator () 함수로 전달할 수 있습니다.
코드 사본은 다음과 같습니다.
var it = iterator (lang, true);
for (var key in it)
인쇄 (키); // 출력 키 값 만 출력합니다
객체에 액세스하기 위해 iterator ()를 사용하는 한 가지 장점은 Object.Prototype에 추가 된 사용자 정의 속성이 시퀀스 객체에 포함되어 있지 않다는 것입니다.
iterator ()는 배열에서도 사용할 수 있습니다.
코드 사본은 다음과 같습니다.
var langs = [ 'JavaScript', 'Python', 'Haskell'];
var it = iterator (langs);
for (var 쌍)
인쇄 (쌍); // 반복 출력 만 [색인, 언어] 키 값 쌍
물체를 가로 지르는 것과 마찬가지로, 두 번째 매개 변수로서 트래버스에 진정을 전달한 결과는 배열 인덱스가됩니다.
코드 사본은 다음과 같습니다.
var langs = [ 'JavaScript', 'Python', 'Haskell'];
var it = iterator (langs, true);
for (var i in it)
인쇄 (i); // output 0, 그런 다음 1, 그런 다음 2
LET 키워드를 사용하여 루프 내에서 변수를 개별적으로 차단하기 위해 색인 및 값을 할당하면 과제 (파괴 할당)를 파괴 할 수도 있습니다.
코드 사본은 다음과 같습니다.
var langs = [ 'JavaScript', 'Python', 'Haskell'];
var it = iterators (langs);
([i, lang]를 놔두려면)
print (i + ':' + lang); // 출력 "0 : javaScript"등
사용자 정의 반복자를 선언하십시오
요소 모음을 나타내는 일부 개체는 지정된 방식으로 반복해야합니다.
1. 범위 (범위)를 나타내는 객체를 반복하면이 범위에 포함 된 숫자를 하나씩 반환해야합니다.
2. 깊이 우선 또는 폭이 먼저 사용하여 트리의 잎 노드에 액세스 할 수 있습니다.
3. 데이터베이스 쿼리 결과를 나타내는 객체를 반복하면 전체 결과 세트가 단일 배열에로드되지 않더라도 행으로 행으로 ROW를 반환해야합니다.
4. 무한 수학적 시퀀스 (Fibonacci 시퀀스와 같은)에서 작용하는 반복자는 무한 길이 데이터 구조를 생성하지 않고 결과를 다시 반환해야합니다.
JavaScript는 반복 논리를 사용자 정의하는 코드를 작성하여 객체에 적용 할 수 있습니다.
두 가지 값으로 간단한 범위 객체를 만듭니다.
코드 사본은 다음과 같습니다.
함수 범위 (낮음, 높은) {
this.low = 낮음;
this.high = 높음;
}
이제 우리는 범위의 모든 정수 시퀀스를 반환하는 사용자 정의 반복기를 만듭니다. 반복자 인터페이스를 사용하려면 다음 요소를 순서에서 반환하거나 스톱 러화 예외를 던지기 위해 다음 () 메소드를 제공해야합니다.
코드 사본은 다음과 같습니다.
함수 범위 기독자 (범위) {
this.range = 범위;
this.current = this.range.low;
}
RangeIterator.prototype.next = function () {
if (this.current> this.range.high)
멈춤을 던지십시오.
또 다른
이를 반환하십시오 .current ++;
};
우리의 RangeItertorator는 전류 시퀀스의 위치를 추적하기 위해 현재 속성을 유지하면서 범위 인스턴스에 의해 인스턴스화됩니다.
마지막으로 범위와 범위와 결합하려면 범위에 특수 __erator__ 메소드를 추가해야합니다. 우리가 범위를 반복하려고 할 때, 그것은 호출되며 반복 논리를 구현하는 RangeIterator의 인스턴스를 반환해야합니다.
코드 사본은 다음과 같습니다.
range.prototype .__ iterator__ = function () {
새로운 RangeIterator (this)를 반환합니다.
};
사용자 정의 반복기를 완료 한 후 스코프 인스턴스를 반복 할 수 있습니다.
코드 사본은 다음과 같습니다.
var 범위 = 새로운 범위 (3, 5);
for (var i in range)
인쇄 (i); // 출력 3, 4, 5
발전기 : 반복자를 구축하는 더 좋은 방법
사용자 정의 반복자는 유용한 도구이지만 명시 적으로 유지해야하므로 만들 때 신중하게 계획해야합니다.
생성기는 강력한 기능을 제공합니다. 자체 반복 알고리즘이 포함 된 함수를 정의 할 수 있으며 상태를 자동으로 유지할 수 있습니다.
발전기는 반복자 공장으로 사용할 수있는 특수 기능입니다. 함수에 하나 이상의 수율 표현식이 포함 된 경우이를 생성기라고합니다 (번역기 참고 : Node.js는 함수 이름 앞에 *로 표시되어야합니다).
참고 : 수율 키워드는 <script type = "application/javaScript; version = 1.7"> (또는 이후)에 포함 된 HTML의 코드 블록에만 사용할 수 있습니다. XUL (XML 사용자 인터페이스 언어) 스크립트 태그는 이러한 기능에 액세스하기 위해이 특수 코드 블록을 지정할 필요가 없습니다.
생성기 함수가 호출되면 기능 본체가 즉시 실행되지 않으면 생성기-고정기 개체를 반환합니다. 생성기-통합기의 다음 () 메소드가 호출 될 때마다 함수 본체는 다음 수율 표현식으로 실행 된 다음 결과를 반환합니다. 함수가 종료되거나 반환 문을 만나면 스톱서 레이션 예외가 발생됩니다.
더 나은 설명을 위해 예제를 사용하십시오.
코드 사본은 다음과 같습니다.
함수 simplegenerator () {
"첫 번째"를 생산합니다.
"두 번째"수율;
"세 번째"를 산출합니다.
for (var i = 0; i <3; i ++)
수율 i;
}
var g = simplegenerator ();
print (g.next ()); // "First"출력
print (g.next ()); // "두 번째"출력
print (g.next ()); // "Third"출력
print (g.next ()); // 출력 0
print (g.next ()); // 출력 1
print (g.next ()); // 출력 2
print (g.next ()); // 스톱 러레이션 예외를 던집니다
발전기 기능은 클래스에서 __iterator__ 메소드로 직접 사용할 수 있으며 사용자 지정 반복자가 필요한 코드의 양을 효과적으로 줄일 수 있습니다. 발전기를 사용하여 범위를 다시 작성해 봅시다.
코드 사본은 다음과 같습니다.
함수 범위 (낮음, 높은) {
this.low = 낮음;
this.high = 높음;
}
range.prototype .__ iterator__ = function () {
for (var i = this.low; i <= this.high; i ++)
수율 i;
};
var 범위 = 새로운 범위 (3, 5);
for (var i in range)
인쇄 (i); // 출력 3, 4, 5
모든 발전기가 종료되는 것은 아니며 무한 시퀀스를 나타내는 발전기를 만들 수 있습니다. 다음 발전기는 피보나치 시퀀스를 구현하며, 각 요소는 처음 두 가지의 합입니다.
코드 사본은 다음과 같습니다.
함수 fibonacci () {
var fn1 = 1;
var fn2 = 1;
(1) {
var current = fn2;
fn2 = fn1;
fn1 = fn1 + 전류;
수율 전류;
}
}
var sequence = fibonacci ();
print (sequence.next ()); // 1
print (sequence.next ()); // 1
print (sequence.next ()); // 2
print (sequence.next ()); // 3
print (sequence.next ()); // 5
print (sequence.next ()); // 8
print (sequence.next ()); // 13
발전기 함수는 매개 변수를 취할 수 있으며 기능을 처음으로 호출 할 때 이러한 매개 변수를 사용합니다. return 문을 사용하여 생성기를 종료 할 수 있습니다. 다음 fibonacci () 변형은 조건이 트리거 될 때 함수를 종료하는 선택적 한계 매개 변수를 취합니다.
코드 사본은 다음과 같습니다.
기능 fibonacci (한계) {
var fn1 = 1;
var fn2 = 1;
(1) {
var current = fn2;
fn2 = fn1;
fn1 = fn1 + 전류;
if (limit && current> Limit)
반품;
수율 전류;
}
}
발전기 고급 기능
생성기는 요구 사항에 따라 수율 반환 값을 계산할 수 있으며, 이는 이전에 비싼 시퀀스 계산 요구 사항, 심지어 위에 표시된 무한 시퀀스를 나타냅니다.
다음 () 메소드 외에도 생성기-타이터 객체는 end () 메소드를 가지며 생성기의 내부 상태를 수정할 수 있습니다. Send ()로 전달 된 값은 마지막 수율 표현의 결과로 처리되며 발전기는 일시 중지됩니다. send () 메소드를 사용하여 지정된 값을 전달하기 전에 다음 ()을 한 번 이상 호출하여 생성기를 시작해야합니다.
다음 Fibonacci 생성기는 send () 메소드를 사용하여 시퀀스를 다시 시작합니다.
코드 사본은 다음과 같습니다.
함수 fibonacci () {
var fn1 = 1;
var fn2 = 1;
(1) {
var current = fn2;
fn2 = fn1;
fn1 = fn1 + 전류;
var Reset = 수율 전류;
if (재설정) {
fn1 = 1;
fn2 = 1;
}
}
}
var sequence = fibonacci ();
print (sequence.next ()); // 1
print (sequence.next ()); // 1
print (sequence.next ()); // 2
print (sequence.next ()); // 3
print (sequence.next ()); // 5
print (sequence.next ()); // 8
print (sequence.next ()); // 13
print (sequence.send (true)); // 1
print (sequence.next ()); // 1
print (sequence.next ()); // 2
print (sequence.next ()); // 3
참고 : 흥미롭게도 Calling Send (undefined)는 다음 () 호출과 정확히 동일합니다. 그러나 새 생성기를 시작하기 위해 send () 메소드가 호출되면 정의되지 않은 것을 제외하고 TypeError 예외가 발생됩니다.
던지기 방법을 호출하고 발전기가 예외를 던지도록 강제로 던지기를 전달할 수 있습니다. 이 예외는 현재 컨텍스트에서 던져지고 현재 수율 실행과 유사한 발전기를 일시 중지하지만 던지기 값 문으로 대체되었습니다.
예외를 던지는 과정에서 수율이 발생하지 않으면, Throw () 메소드가 호출 될 때까지 예외가 전달되며, 다음에 전화하면 stopEration 예외가 발생하게됩니다.
생성기에는 생성기가 종료되도록하는 Close () 메소드가 있습니다. 생성기 종료는 다음과 같은 영향을 미칩니다.
1. 발전기의 모든 유효한 문장이 실행됩니다.
2. 마침내 단어가 스톱 러화를 제외하고 예외를 던지면 예외는 close () 메소드의 발신자에게 전달됩니다.
3. 발전기가 종료됩니다
발전기 표현식
배열 도출의 명백한 단점 중 하나는 전체 배열을 메모리로 구성한다는 것입니다. 오버 헤드가 작은 배열 자체 인 경우 파생에 입력하는 오버 헤드는 중요하지 않습니다. 그러나 입력 어레이가 클 때 또는 새로운 비싼 (또는 무한) 배열 생성기를 생성 할 때 문제가 발생할 수 있습니다.
생성기를 통해 게으른 컴퓨팅은 필요할 때 필요한 경우 요소를 계산할 수 있습니다. 발전기 표현식은 배열 파생과 거의 동일합니다. 사각형 브래킷 대신 괄호를 사용하고 (각각 ... in) 대신 사용합니다. 그러나 계산이 지연 될 수 있도록 배열 대신 생성기를 생성합니다. 발전기를 만들기위한 간단한 구문으로 생각할 수 있습니다.
우리가 거대한 정수를 반복하기 위해 반복자를 가지고 있다고 가정 해 봅시다. 짝수를 반복하려면 새로운 반복자를 만들어야합니다. 배열 파생은 메모리의 모든 짝수 숫자를 포함하는 전체 배열을 만듭니다.
코드 사본은 다음과 같습니다.
변수 복식 = [i * 2 for (i in in in)];
생성기 표현식은 새로운 반복기를 생성하고 필요할 때 필요에 따라 짝수 값을 계산합니다.
코드 사본은 다음과 같습니다.
var it2 = (i * 2 for (i in it));
print (it2.next ()); // 첫 번째 짝수 숫자
print (it2.next ()); // 두 번째 짝수 숫자
생성기가 함수의 매개 변수로 사용되면 괄호는 함수 호출로 사용됩니다. 즉, 가장 바깥 쪽 괄호는 생략 될 수 있음을 의미합니다.
코드 사본은 다음과 같습니다.
var result = dosomething (i * 2 for (i in in in));
끝.