이 글은 자바스크립트에 대한 관련 지식을 주로 소개하며, 필요한 친구들이 참고할 수 있기를 바랍니다.
마스터 과정에 대한 프런트 엔드(vue) 항목: 학습 항목 입력
Iterator는 다양한 데이터 구조에 대한 통합 액세스 메커니즘을 제공하는 통합 인터페이스 메커니즘을 제공합니다.
Iterator를 정의하는 것은 next()가 호출될 때마다 결과 객체가 반환되며, value는 현재 값을 나타내고, done은 순회 완료 여부를 나타냅니다. .
함수 makeIterator(배열){ 인덱스 = 0으로 놔두세요; 반품 { 다음: 함수(){ 반품 ( Array.length > 인덱스 ? {값: 배열[색인++]}: {완료: 사실} ) } } } 반복자 = makeIterator(['1','2']) console.log(iterator.next()); // {값: '1'} console.log(iterator.next()); // {값: '2'} console.log(iterator.next()); // {완료: true}
반복자의 역할:
다양한 데이터 구조에 대한 통합되고 간단한 액세스 인터페이스를 제공합니다.
데이터 구조의 구성원을 특정 순서로 정렬할 수 있습니다.
for...of의 소비용
ES6에서는 반복자 객체를 순회하는 for of 문을 제공합니다. 위에서 생성한 반복자를 순회하기 위해 for of 문을 사용할 것입니다.
반복자 = makeIterator(['1','2']) for (반복자의 값을 알려주세요) { console.log(값); } // 반복자는 반복 가능하지 않습니다.
결과적으로 반복자가 반복 가능하지 않다는 오류가 발생합니다. 이유는 무엇입니까? ES6에서는 기본 Iterator 인터페이스가 데이터 구조의 Symbol.iterator 속성에 배포되도록 규정합니다. 데이터 구조에 Symbol.iterator 속성이 있으면 데이터 구조를 탐색할 수 있습니다.
사용자 정의 makeIterator를 다음과 같이 변환합니다.
const MakeIterator = (배열) => ({ [Symbol.iterator](){ 인덱스 = 0으로 놔두세요; 반품 { 다음(){ 길이 = Array.length; if(인덱스 < 길이){ {값: 배열[index++]}를 반환합니다. }또 다른{ 반환 {완료: true} } } } } }) for(MakeIterator([1,2])의 값을 설정){ console.log(값) } // 1 // 2
MakeIterator에 반환 메서드를 추가합니다. for...of 루프가 일찍 종료되면(보통 오류나 break 문으로 인해) return() 메서드가 호출되어 순회를 종료합니다.
이 기능을 기반으로 순회를 완료하기 전에 개체가 리소스를 정리하거나 해제해야 하는 경우 return() 메서드를 배포하고 파일 읽기가 실패할 때 파일을 닫는 것을 포함할 수 있습니다.
const MakeIterator = (배열) => ({ [Symbol.iterator](){ 인덱스 = 0으로 놔두세요; 반품 { 다음(){ 길이 = Array.length; if(인덱스 < 길이){ {값: 배열[index++]}를 반환합니다. }또 다른{ 반환 {완료: true} } }, 반품(){ 반환 {완료: true} } } } }) for(MakeIterator의 값([1, 2, 3])){ console.log(값) // 1 // 방법 1 부서지다; // 방법 2 // 새로운 오류 발생('error'); }
정렬
세트
지도
인수 객체, DOM NodeList 객체, typedArray 객체와 같은 배열 유사 객체
// 인수 객체 함수 sum(){ for(인수의 값을 알려주세요){ console.log(값) } } 합(1,2) // 1 // 2 // typedArray 객체 let typeArry = new Int8Array(2); typeArry[0] = 1; typeArry[1] = 2; for(typeArry의 값을 알려주세요){ console.log(값) } // 1 // 2
생성기 객체
함수*gen(){ 수율 1; 수율 2; } for(gen()의 값을 알려주세요){ console.log(값) }
끈
Q: 객체에 기본 Iterator가 없는 이유는 무엇입니까?
A: Object가 기본적으로 Iterator 인터페이스를 배포하지 않는 이유는 객체의 어떤 속성이 먼저 탐색되고 어떤 속성이 나중에 탐색되는지 확실하지 않기 때문입니다.
본질적으로 트래버스는 선형 프로세스입니다. 비선형 데이터 구조의 경우 트래버스 인터페이스 배포는 선형 변환 배포와 동일합니다.
그러나 엄밀히 말하면 객체 배치 트래버스 인터페이스는 이때 객체가 실제로 Map 구조로 사용되기 때문에 필요하지 않습니다. ES5에는 Map 구조가 없지만 ES6에서는 이를 기본적으로 제공합니다.
구조분해 할당
set = new Set().add('a').add('b').add('c'); let [x,y] = 설정; // x='a';
스프레드 연산자
var str = '안녕하세요'; [...str] // ['h','e','l','l','o']
Spread 연산자는 Iterator 인터페이스를 호출하므로 Object는 Iterator 인터페이스를 배포하지 않습니다. 그런데 왜... 연산자를 사용할 수 있습니까?
이유: 스프레드 연산자에는 두 가지 유형이 있습니다.
하나는 함수 매개변수 및 배열 확장의 경우에 사용됩니다. 이 경우 객체는 반복 가능해야 합니다.
다른 하나는 객체 확장을 위한 것, 즉 {...obj} 형식입니다. 이 경우 객체는 열거 가능(enumerable)해야 합니다.
obj1 = {라고 놔두세요 이름 : 'qianxun' } obj2 = {라고 놔두세요 나이: 3 } // 배열 객체는 열거 가능합니다. let obj = {...obj1, ...obj2} console.log(obj) //{이름: 'qianxun', 연령: 3} // 일반 객체는 기본적으로 반복 가능하지 않습니다. let obj = [...obj1, ...obj2] console.log(obj) // 객체는 반복 가능하지 않습니다.
함수 forOf(obj, cb){ let iteratorValue = obj[Symbol.iterator](); 결과 = iteratorValue.next()로 설정 동안(!결과.완료){ cb(결과.값) 결과 = iteratorValue.next() } } forOf([1,2,3], (값)=>{ console.log(값) }) // 1 // 2 // 3
개념적으로
Generator 함수는 ES6에서 제공하는 비동기 프로그래밍 솔루션입니다. Generator 함수는 여러 내부 상태를 캡슐화하는 상태 머신입니다.
Generator 함수는 실행 후 traverser 객체를 반환하는 traverser 객체 생성 함수이기도 합니다.
공식적인
1. 함수 키워드와 함수 이름 사이에 별표가 있습니다.
2. 함수 본문 내에서 항복 표현식을 사용하여 다양한 내부 상태를 정의합니다.
함수* simpleGenerator(){ 수율 1; 수율 2; } 단순생성기()
위와 같이 간단한 제너레이터를 생성하고 두 가지 질문으로 이를 탐색했습니다.
Generator 함수가 실행된 후에는 어떻게 되나요?
함수의 항복 표현식은 무엇을 합니까?
함수* simpleGenerator(){ console.log('안녕하세요 세계'); 수율 1; 수율 2; } let Generator = simpleGenerator(); // simpleGenerator {<일시중단됨}} console.log(generator.next()) //안녕하세요 세상 // {값: 1, 완료: false} console.log(generator.next()) // {값: 2, 완료: false}
Generator 생성기 함수는 실행 후 생성기 개체를 반환하는 반면, 일반 함수는 생성기 개체의 다음 메서드가 호출될 때마다 함수 내부의 코드를 직접 실행하며 다음 Yield 키워드 실행이 중지될 때까지 함수가 실행됩니다. {value: Value, done: Boolean} 객체.
항복 표현식 자체에는 반환 값이 없거나 항상 정의되지 않은 값을 반환합니다. 다음 메소드는 하나의 매개변수를 취할 수 있으며, 이는 이전 항복 표현식의 반환 값으로 처리됩니다. 다음 메소드의 매개변수를 통해 Generator 함수의 여러 단계에서 외부에서 내부로 다양한 값을 주입하여 함수 동작을 조정할 수 있습니다. next 메서드의 매개 변수는 이전 항복 표현식의 반환 값을 나타내므로 다음 메서드를 처음 사용할 때 매개 변수 전달이 유효하지 않습니다.
함수 합(x){ 반환 함수(y){ x + y를 반환합니다. } } console.log(합계(1)(2)) // 다음 매개변수를 사용하여 function* sum(x){를 다시 작성합니다. y = x를 산출하자; 동안(참){ y = x + y를 산출합니다. } } gen = sum(2)이라고 하자 console.log(gen.next()) // 2 console.log(gen.next(1)) // 3 console.log(gen.next(2)) // 4
Yield 표현식의 역할: 내부 상태 정의 및 실행 일시 중지 Yield 표현식과 return 문의 차이점
Yield 표현식은 함수가 실행을 일시 중지하고 다음 번에 해당 위치부터 뒤로 계속 실행된다는 것을 의미하는 반면, return 문에는 위치 메모리 기능이 없습니다.
함수에서는 하나의 return 문만 실행할 수 있지만 여러 개의 Yield 표현식을 실행할 수 있습니다.
모든 함수는 return 문을 사용할 수 있습니다. Yield 표현식은 Generator 함수에서만 사용할 수 있습니다. 다른 곳에서 사용하면 오류가 보고됩니다.
Yield 표현식이 연산에 참여하는 경우에는 괄호 안에 넣어야 하며, 함수 매개변수로 사용되거나 할당 표현식의 오른쪽에 배치되는 경우에는 괄호가 포함되지 않을 수 있습니다.
함수 *gen () { console.log('hello' + 항복) × console.log('hello' + (yield)) √ console.log('hello' + 항복 1) × console.log('hello' + (수율 1)) √ foo(수율 1) √ const param = 산출량 2 √ }
Generator 생성기 함수가 여러 산출물을 지원할 수 있다는 사실을 기반으로 함수에 여러 반환 값이 있는 시나리오를 구현할 수 있습니다.
함수* gen(숫자1, 숫자2){ 수율 num1 + num2; 수율 num1 - num2; } res = gen(2, 1); console.log(res.next()) // {value: 3, done: false} console.log(res.next()) // {값: 1, 완료: false}
Generator 함수는 반복자 생성 함수이므로 객체의 Symbol.iterator 속성에 Generator를 할당하여 객체가 Iterator 인터페이스를 가질 수 있습니다. 생성기 구현 코드가 더 간결해졌습니다.
obj = {라고 놔두세요 이름: 'qianxun', 나이: 3, [Symbol.iterator]: 함수(){ 저것 = 이것으로 놔두세요; 키 = Object.keys(그)를 보자 인덱스 = 0으로 놔두세요; 반품 { 다음: 함수(){ 반환 인덱스 <keys.length? {값: that[keys[index++]], 완료: false}: {값: 정의되지 않음, 완료: true} } } } } for(obj의 값을 알려주세요){ console.log(값) }
발전기:
obj = {라고 놔두세요 이름: 'qianxun', 나이: 3, [Symbol.iterator]: 함수* (){ 키 = Object.keys(this)를 보자 for(let i=0; i< 키.길이; i++){ 항복 this[키[i]]; } } } for(obj의 값을 알려주세요){ console.log(값) }
return()
메소드는 주어진 값을 반환하고 순회 생성기 함수를 종료할 수 있습니다.
함수*gen() { 수율 1; 수율 2; 수율 3; } var g = gen(); g.next() // { 값: 1, 완료: false } // return() 메서드가 호출될 때 매개 변수가 제공되지 않으면 반환 값의 value 속성이 정의되지 않습니다. g.return('foo') // { 값: "foo", 완료: true } g.next() // { 값: 정의되지 않음, 완료: true }
Generator 함수 내에 try...finally
코드 블록이 있고 try
코드 블록이 실행 중인 경우 return()
메서드를 사용하면 실행 후 finally
코드 블록이 즉시 입력됩니다.
함수* 숫자 () { 수율 1; 노력하다 { 수율 2; 수율 3; } 마지막으로 { 수율 4; 수율 5; } 수율 6; } var g = 숫자(); g.next() // { 값: 1, 완료: false } g.next() // { 값: 2, 완료: false } g.return(7) // { 값: 4, 완료: false } g.next() // { 값: 5, 완료: false } g.next() // { 값: 7, 완료: true }
Generator 함수 내에서 다른 Generator 함수를 호출하려는 경우. 전자의 함수 본문 내에서 순회를 수동으로 완료해야 합니다. 함수 호출이 여러 수준에 중첩되어 있으면 쓰기가 번거롭고 읽기 어려울 수 있습니다. ES6은 이에 대한 해결책으로 Yield* 표현식을 제공합니다.
다른 생성자에게 위임
함수* g1() { 수율 2; 수율 3; } 함수* g2() { 수율 1; 수율* g1(); 수율 4; } const 반복자 = g2(); console.log(iterator.next()); // { 값: 1, 완료: false } console.log(iterator.next()); // { 값: 2, 완료: false } console.log(iterator.next()); // { 값: 3, 완료: false } console.log(iterator.next()); // { 값: 4, 완료: false } console.log(iterator.next()); // { 값: 정의되지 않음, 완료: true }
다른 반복 가능한 객체에 위임
함수*gen(){ 수익률* [1,2,3] } console.log(gen().next()) // {value: 1, done: false}
Generator 함수는 트래버스를 반환합니다. ES6에서는 이 트래버스가 Generator 함수의 인스턴스이고 Generator.prototype 객체의 메서드를 상속한다고 규정하지만, 이는 현재 인스턴스가 아닌 전역 객체이기 때문에 이에 대한 속성을 얻을 수 없습니다. 물체.
함수*gen(){ this.a = 1 } gen.prototype.say = 함수(){ console.log('안녕') } obj = gen()이라고 놔두세요 console.log(obj instanceof gen) // 참 obj.say() // 안녕하세요 obj.next() console.log(obj.a) //정의되지 않음
생성자와 같은 인스턴스 속성에 액세스하려면 이를 수정하여 Generator.prototype에 바인딩할 수 있습니다.
함수*gen(){ this.a = 1 } gen.prototype.say = 함수(){ console.log('안녕') } obj = gen.call(gen.prototype)으로 설정하세요. console.log(obj instanceof gen) // 참 obj.say() // 안녕하세요 obj.next() console.log(obj.a) //1
함수* StateMachine(상태){ 전환하자; 동안(참){ if(전환 === "증가"){ 상태++; }else if(전환 === "감소"){ 상태--; } 전이 = 항복 상태; } } const 반복자 = StateMachine(0); console.log(iterator.next()); // 0 console.log(iterator.next('INCREMENT')) // 1 console.log(iterator.next('DECREMENT')) // 0