generator(一)-generator기초와iterator의 관계를 상세히 설명하다
generator 기초
generator의 구조와 함수의 구성은 같지만 성명 형식이 다르다. 예를 들어
function *foo(){}
또는 function*foo(){}
(공칸 없음) 이다.먼저 generator의 간단한 예를 봅시다.
let a=1
function *foo(){
a++
yield
console.log(`a:${a}`)
}
function bar(){
a++
}
// it generator
const it=foo()
// foo()
it.next() // a->2
bar() // a->3
it.next() // : a:3
기억해!첫 번째next()는 초기화 시작generator입니다.
입력 출력
1. 교체 메시지 전달
function *foo(x){
const y=x*(yield)
return y
}
const it=foo(2)
// *foo(),
it.next() // ->{value: undefined, done: false}
// 3 yield , const y=2*3
const res=it.next(3) // ->{value: 6, done: true}
res.value // 6
첫 번째
next()
는 항상 시작해야 하기 때문에generator
와next()
는 일일이 일치하지 않습니까?2. 양방향 메시지 전달
우리는 교체기의 측면에서
yield
과next()
의 관계를 본다. yield
는 하나의 표현식으로서 메시지 응답yield ...
을 호출할 수 있고, next(..)
도 일시 정지된 next(..)
표현식에 값을 보낼 수 있다. 메시지는 양방향으로 전달된다.위의 예를 고치십시오.
function *foo(x){
const y=x*(yield 'hello')
return y
}
const it=foo(2)
it.next() //-> {value: "hello", done: false}
it.next(3) // ->{value: 6, done: true}
generator 시작 부분에서, 우리가 첫 번째
yield
를 호출할 때, 아직 멈추지 않은 next()
은 이 값을 받아들인다.첫 번째yield
의 호출은 기본적으로 하나의 문제를 제기한다. generatornext()
가 나에게 줄 다음 값이 무엇인지, 첫 번째*foo
가 이 문제를 대답한다.다중 교체기
일반적인 함수에서 두 함수를 교체하여 실행하는 것은 불가능하다!A 함수가 먼저 실행되거나, B 함수가 먼저 실행됩니다.
그러나generator를 사용하여 교체하여 집행하는 것은 분명히 능숙하다!
let a=1
let b=2
function *foo(){
a++
yield
b=b*a
a=(yield b)+3
}
function *bar(){
b--
yield
a=(yield 8)+b
b=a*(yield 2)
}
상기 두 개generator는 공유된 같은 변수에서 교체하여 실행하고 교체기의 제어에 따라 앞의 프로그램은 여러 가지 다른 결과를 낼 수 있다.
우리는 교체기를 제어하기 위해 보조 함수를 만듭니다.
function step(gen){
let it=gen()
let last;
return function(){
// yield ,
last=it.next(last).value
}
}
교대 운행
yield 'hello'
과 *foo()
을 시험해 보겠습니다.const s1=step(foo)
const s2=step(bar)
s2() // b-- b=1
s2() // yield 8
s1() // a++ a=2
s2() // a=8+b a=9
// yield 2
s1() // b=b*a b=9
// yield b
s1() // a=b+3 12
s2() // b=a*2 18 a 9
console.log(a,b) // 12 18
generator의 생성값
이전 절에서는 주로generator가 값을 생성하는 방식을 소개했는데 이 절에서는 더욱 기초적인 것을 소개할 것이다.
iterator
만약에 당신이 일련의 값을 생성하려고 한다면 모든 값은 이전과 특정한 관계를 가진다. 이것이 바로 교체 과정이다.iterator는generator에서 한 걸음 한 걸음 일련의 값을 얻을 수 있도록 정의된 좋은 인터페이스입니다.generator에서 다음 값을 얻으려면 호출해야 합니다
*bar()
.함수 클러치로 교체기를 구성하다
우리는 간단한 함수 패키지 구조로 숫자의 교체 과정을 생성할 수 있다.
const gimmeSomething = (() => {
let nextVal;
return () => {
if (nextVal === undefined) {
nextVal = 1
} else {
nextVal = (3 * nextVal) + 6
}
return nextVal
}
})()
gimmeSomething() //1
gimmeSomething() //9
gimmeSomething() // 33
...
우리는
next()
인터페이스를 하나 더 구성합니다.const something=(()=>{
let nextVal
return {
[Symbol.iterator]:function(){return this}, //
next:()=>{
if(nextVal===undefined){
nextVal=1
}else{
nextVal=nextVal*3+6
}
return {done:false,value:nextVal}
}
}
})()
자동 교체
es6에 추가된
next()
순환은 자동으로 표준 교체기를 교체할 수 있습니다.for (var v of something) {
console.log(v)
if (v > 300) break;
}
// 1 9 33 105 321
다음 예제를 변경합니다.
const something = (() => {
let nextVal
return {
[Symbol.iterator]: function() {
return this
},
next: () => {
if (nextVal === undefined) {
nextVal = 1
} else {
nextVal = nextVal * 3 + 6
}
return {
done: nextVal>300,
value: nextVal
}
}
}
})()
for (var v of something) {
console.log(v) // 1 9 33 105
}
for...of
순환은 매번 교체할 때마다 자동으로 호출됩니다 for..of..
. 순환은 next()
에 어떤 값도 전송되지 않으며 next()
받아들일 때 멈춥니다.사용자 정의iterator를 구성하는 것 외에 그룹에도 기본 교체기가 있습니다.
const a=[1,5,15,25]
for (var v of a) {
console.log(v) // 1,5,15,25
}
일반적인object는
done:true
같은 기본 교체기가 없습니다. 대상의 모든 속성을 교체하려면 array
을 통해array를 되돌려주고 Object.keys(..)
이 키 명수 그룹을 교체합니다. (주의: for..of..
는 원형 체인에서 온 속성을 포함하지 않습니다. Object.keys
는 포함됩니다.2.iterable
iterable은 그 값에 교체할 수 있는 교체기를 포함하는 대상을 가리킨다. 그의 이름은 기호값
for..in..
이다. 이 함수를 호출할 때 교체기를 되돌려준다.Symbol.iterator
순환 자동 호출 for..of
함수로 교체기를 구축합니다.이전 절에서 사용한
Symbol.iterator
교체수 그룹의 예는const a=[1,5,15,25]
const it=a[Symbol.iterator]()
it.next().value //1
it.next().value //5
it.next().value // 15
3. 생성기 교체기
우리는genrator를 하나의 값의 생산자로 볼 수 있으며, 우리는 교체기 인터페이스
for..of
를 통해 한 번에 하나의 값을 추출할 수 있다.generator를 실행할 때iterator를 얻을 수 있습니다.우리는
next()
로 이전 무한 디지털 서열 생산자generator
를 실현했다.function *something(){
let nextVal
while(true){
if(nextVal===undefined){
nextVal=1
}else{
nextVal=nextVal*3+6
}
yield nextVal
}
}
일반적으로 우리는 js 프로그램을 작성할 때
something
을 사용하고 그 중에서 퇴출 문장이 없을 때 매우 나쁜 설계를 한다. 만약 생성기에 while(true)
이 있다면, 이러한 순환을 사용하는 것은 전혀 문제가 없다.생성기가 매번 교체될 때마다 멈추기 때문에, yield
을 통해 메인 프로그램이나 시간 순환 대기열로 되돌아옵니다.yield
를 사용하여 이 생성기를 순환합니다.for(let v of something()){
console.log(v)
if(v>300) break; // 1 9 33 105 321
}
우리는 우선
for..of
을 사용해야만 generator -> iterator
교체를 할 수 있기 때문에 먼저 for .. of
생산자를 구성하여 something()
순환 교체를 할 수 있다.generator의 교체기iterable에도 for..of..
함수가 있기 때문에iterable이기도 하다.생성기 중지
위의 예에서generator
Symbol.iterator
의 교체기 실례는 순환 중*something()
이후 영원히 정지 상태에 머무르는 것 같다.사실상
break
에서 순환하는'이상 종료'(조기 종료)는 통상적으로break,return 또는 미포획 이상으로 인해generator의 교체기에 신호를 보내서 종료시킨다.for..of
문장을 사용하여generator를 구축합니다. generator가 외부에서 끝났더라도finally의 문장은 실행됩니다. 자원을 정리할 수 있습니다. 예를 들어 다음과 같습니다.function *something(){
try{
let nextVal
while(true){
if(nextVal===undefined){
nextVal=1
}else{
nextVal=nextVal*3+6
}
yield nextVal
}
}
finally{
console.log('clean up')
}
}
for(let v of something()){
console.log(v)
if(v>300) break; // 1 9 33 105 321 'clean up'
}
위의 예에서break는finally문장을 촉발한다.우리도
try..finally..
수동으로 생성기를 종료하는 교체기 실례를 사용할 수 있다.const it=something()
for(let v of it){
console.log(v)
if(v>300){
console.log(
it.return('end up!!').value
)
// break
}
}
// 1 9 33 105 321
// clean up!
// end up!!
it.return()
를 호출하면 생성기를 즉시 종료하고finally의 문장을 터치하며 되돌아오는 value를 it.return()
에 전송된 내용으로 설정하고done는true, 즉 return()
가 전송되는 과정, end up!
순환이 종료됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.