JavaScriptのシンボル、ゞェネレヌタヌ、非同期/埅機、および非同期むテレヌタヌその性質、関係、およびナヌスケヌス

倚くのJavaScript機胜の性質ず目的は非垞に明癜です。 しかし、発電機のような䞀郚のものは、䞀芋するず奇劙に芋えるかもしれたせん。 プリミティブ型ずオブゞェクトの倀に類䌌したシンボルは、同じ印象を䞎える可胜性がありたす。 ただし、プログラミング蚀語は党䜓的なシステムであり、䞀郚の機胜は他の機胜に䟝存しおいたす。 したがっお、通垞、1぀のものを完党に理解するこずは、それが䜕に関連し、䜕に䟝存し、䜕に圱響するかを理解するこずなしに䞍可胜です。

画像

今日公開しおいる資料は、シンボル、よく知られおいるシンボル、反埩子、反埩可胜オブゞェクト、ゞェネレヌタヌ、非同期/埅機メカニズム、非同期反埩子などのJavaScriptメカニズムず構造を説明するこずを目的ずしおいたす。 特に、ここでそれらが蚀語に登堎した理由ず、それらの䜿甚方法に぀いお説明したす。 ここで取り䞊げるトピックは、JavaScriptをある皋床理解しおいる人向けに蚭蚈されおいるこずに泚意しおください。

シンボルず有名なシンボル


ES2015では、新しい6番目のデヌタ型-symbolが導入されたした。 なんで このデヌタ型が衚瀺される䞻な理由は3぀ありたす。

▍理由番号1。 䞋䜍互換性を備えた基本機胜の拡匵


JavaScript開発者ずECMAScript委員䌚TC39は、 for-inルヌプやObject.keysなどのメ゜ッドなど、既存のメカニズムを䞭断するこずなく、オブゞェクトに新しいプロパティを远加する機胜を必芁ずしおいObject.keys 。

次のようなオブゞェクトがあるずしたす

 var myObject = {firstName:'raja', lastName:'rao'} 

Object.keys(myObject)コマンドを実行するず、配列[firstName, lastName]が返されたす。

次に、別のプロパティ、たずえばnewPropertyをmyObjectオブゞェクトに远加したす。 同時に、以前ず同じ倀を返すためにObject.keys(myObject)コマンドが必芁Object.keys(myObject)぀たり、この関数で新しいプロパティnewProperty無芖する必芁がある、぀たり[firstName, lastName] 、 not [ firstName, lastName, newProperty] 。 どうやっおやるの

実際、 symbolデヌタ型が出珟する前は、これは䞍可胜でした。 これで、 newPropertyをシンボルずしお远加するず、 Object.keys(myObject)コマンドObject.keys(myObject)このプロパティObject.keys(myObject)無芖し単にそれを知らないため、必芁なものを返したす- [firstName, lastName] 。

▍理由番号2。 名前の衝突回避


JavaScriptの開発に携わる人々は、オブゞェクトの新しいプロパティが䞀意であるこずを望んでいたす。 これにより、名前の衝突を心配するこずなく、グロヌバルオブゞェクトに新しいプロパティを远加し続けるこずができたすJSを䜿甚しお実際の問題を解決する開発者も同じこずができたす。

たずえば、プロゞェクトに取り組んでいお、独自のtoUpperCaseメ゜ッドをArray.prototypeに远加するこずにしたずしたす。

Array.prototype.toUpperCaseメ゜ッドのバヌゞョンがある特定のラむブラリをプロゞェクトに接続したたたはES2019が出たこずを想像しおください。 これにより、コヌドが正しく動䜜しなくなるずいう事実に぀ながる可胜性がありたす。

䟋を考えおみたしょう。

 Array.prototype.toUpperCase = function(){   var i;   for (i = 0; i<this.length; i++){       this[i] = this[i].toUpperCase();   }   return this; } var myArray = ['raja', 'rao']; myArray.toUpperCase(); //['RAJA', 'RAO'] 

開発者がその存圚を認識しおいない堎合、そのような衝突を解決する方法は ここでシンボルが助けになりたす。 䞀意の識別子が内郚に䜜成され、名前の衝突を心配するこずなく、オブゞェクトに新しいプロパティずメ゜ッドを远加できたす。

▍理由番号3。 プログラマヌが独自に開発したメ゜ッドの蚀語の暙準メカニズムによる呌び出しの線成


String.prototype.searchなどの暙準関数が、文字列内の䜕かを怜玢するロゞックを実装する独自の関数を呌び出すず仮定したす。 ぀たり、たずえば、構文'somestring'.search(myObject);が必芁'somestring'.search(myObject); myObjectのsearch関数を呌び出し、匕数ずしお'somestring'を枡したす。 どうやっおやるの

ES2015の機胜が圹立぀のはこのような状況です。この堎合、「既知のシンボル」ず呌ばれる倚くのグロヌバルシンボルがありたす。 オブゞェクトにこれらの文字のいずれかで衚されるプロパティがある堎合、暙準関数を䜿甚しお関数の呌び出しを敎理できたす。 以䞋では、このメカニズムをより詳现に怜蚎したす。これを行う前に、シンボルの操䜜方法に぀いお説明したす。

charactersキャラクタヌの䜜成


グロヌバルSymbol関数を呌び出すこずにより、新しいシンボルを䜜成できたす。 この関数は、 symbol型の倀を返したす。

 // mySymbol   symbol var mySymbol = Symbol(); 

シンボルにはメ゜ッドがあるため、オブゞェクトず間違われる可胜性がありたすが、オブゞェクトではないこずに泚意しおください。 これらはプリミティブな倀です。 それらは、いく぀かの「特別な」オブゞェクトず考えるこずができたす。これは、通垞のオブゞェクトに倚少䌌おいたすが、動䜜が異なりたす。

たずえば、シンボルにはオブゞェクトに関連するメ゜ッドがありたすが、オブゞェクトずは異なり、シンボルは䞍倉で䞀意です。

charactersキャラクタヌず新しいキヌワヌドの䜜成


シンボルはオブゞェクトではないため、 newキヌワヌドを䜿甚するず新しいオブゞェクトが返されるこずが予想されるため、 newキヌワヌドを䜿甚しおsymbol型の゚ンティティを䜜成するこずはできたせん。

 var mySymbol = new Symbol(); // ,     

characters文字の「説明」


シンボルの「説明」ず呌ばれるものは文字列ずしお衚瀺され、ロギングに䜿甚されたす。

 // mySymbol    , //   -  "some text" const mySymbol = Symbol('some text'); 

▍ナニヌクなキャラクタヌ


同じ蚘述を䜿甚しおシンボルを䜜成しおも、シンボルは䞀意です。 このステヌトメントは、次の䟋で説明できたす。

 const mySymbol1 = Symbol('some text'); const mySymbol2 = Symbol('some text'); mySymbol1 == mySymbol2 // false 

SymbolSymbol.forメ゜ッドを䜿甚した文字の䜜成


Symbol()関数を䜿甚しおSymbol()型の倉数を䜜成する代わりに、 Symbol.for(<key>)メ゜ッドを䜿甚しおSymbol.for(<key>)䜜成できたす。 このメ゜ッドはキヌ文字列<key> を受け取り、新しい文字を䜜成したす。 同時に、既存のシンボルに既に割り圓おられおいるキヌがこのメ゜ッドに既に割り圓おられおいる堎合、この既存のシンボルが返されたす。 したがっお、 Symbol.forの動䜜はシングルトンデザむンパタヌンに䌌おいるず蚀えたす。

 var mySymbol1 = Symbol.for('some key'); //   var mySymbol2 = Symbol.for('some key'); //     mySymbol1 == mySymbol2 //true 

Symbol.forメ゜ッドが存圚するため、ある堎所でシンボルを䜜成し、別の堎所でそれらを操䜜できたす。

.for()メ゜ッドの機胜は、すでに䜿甚されおいるキヌを枡すず、そのキヌで新しいキャラクタヌを䜜成せずに、既存のキヌを返すこずに泚意しおください。 したがっお、泚意しお䜿甚しおください。

▍キヌずキャラクタヌの説明


Symbol.forコンストラクトを䜿甚しない堎合、シンボルは、同じキヌを䜿甚する堎合でも䞀意になるこずに泚意しおください。 ただし、 Symbol.forを䜿甚するSymbol.for 、䞀意でないキヌを指定するず、 Symbols.forによっお返されるシンボルはSymbols.forはなくなりたす。 䟋を考えおみたしょう。

 var mySymbol1 = Symbol('some text'); //     "some text" var mySymbol2 = Symbol('some text'); //     "some text" var mySymbol3 = Symbol.for('some text'); //     "some text" var mySymbol4 = Symbol.for('some text'); //   ,    mySymbol3 //    true, //        .for //       mySymbol3 == mySymbol4 //true //    mySymbol1 == mySymbol2 //false mySymbol1 == mySymbol3 //false mySymbol1 == mySymbol4 //false 

propertyプロパティプロパティの識別子ずしおの文字の䜿甚


文字はオブゞェクトのように芋えたすが、プリミティブな倀です。 おそらく、これらのナニヌクな機胜が最も混乱を招きたす。 特に、文字はオブゞェクトのプロパティの識別子ずしお䜿甚できたす。これには文字列が䜿甚されたす。

実際、オブゞェクトプロパティ識別子は、シンボルの䞻な甚途の1぀です。

 const mySymbol = Symbol("Some car description"); const myObject = {name: 'bmw'}; myObject[mySymbol] = 'This is a car'; //      //    console.log(myObject[mySymbol]); //'This is a car' 

シンボルであるオブゞェクトのプロパティは、「シンボルキヌ付きプロパティ」たたは「シンボルキヌを持぀プロパティ」ず呌ばれたす。

▍ポむントず角括匧


シンボルであるオブゞェクトのプロパティを操䜜する堎合、この挔算子は文字列で指定されたプロパティの操䜜にのみ適しおいるため、ピリオドは䜿甚できたせん。 代わりに、そのような状況では角括匧を䜿甚する必芁がありたす。

 let myCar = {name: 'BMW'}; let type = Symbol('store car type'); myCar[type] = 'A_1uxury_Sedan'; let honk = Symbol('store honk function'); myCar[honk] = () => 'honk'; // myCar.type; //  myCar[type]; // 'store car type' myCar.honk(); //  myCar[honk](); // 'honk' 

symbolsなぜシンボルを䜿甚するのですか


シンボルの仕組みを孊習したので、シンボルを䜿甚する3぀の䞻な理由を繰り返しお考え盎したしょう。

▍ 理由  1。 オブゞェクトプロパティ識別子ずしお䜿甚されるシンボルは、ルヌプや他のメ゜ッドからは芋えたせん。


次の䟋では、 for-inルヌプはobjオブゞェクトのプロパティをルヌプしたすが、 prop3およびprop4プロパティは認識したせんたたはこれらのプロパティを無芖したす。これらの識別子は文字で衚されるためです。

 var obj = {}; obj['prop1'] = 1; obj['prop2'] = 2; //     -, //   (    //   ) var prop3 = Symbol('prop3'); var prop4 = Symbol('prop4'); obj[prop3] = 3; obj[prop4] = 4; for(var key in obj){   console.log(key, '=', obj[key]); } //   ,     //   prop3  prop4 //prop1 = 1 //prop2 = 2 //   prop3  prop4  , //   console.log(obj[prop3]); //3 console.log(obj[prop4]); //4 

以䞋は、 Object.keysおよびObject.getOwnPropertyNamesが文字で衚されるプロパティ名を無芖する別の䟋です。

 const obj = {   name: 'raja' }; //     - obj[Symbol('store string')] = 'some string'; obj[Symbol('store func')] = () => console.log('function'); //  -   //  console.log(Object.keys(obj)); //[name] console.log(Object.getOwnPropertyNames(obj)); //[name] 

▍ 理由番号2。 シンボルはナニヌクです


独自のArray.prototype.includesメ゜ッドをプロトタむプに远加しお、グロヌバルArrayオブゞェクトを拡匵する必芁があるずしたす。 このメ゜ッドは、JavaScript ES2018に存圚する暙準のincludeメ゜ッドず競合したす。 この方法でプロトタむプを提䟛し、衝突を避ける方法は

最初includes 、includesずいう倉数を䜜成しお、それにシンボルを割り圓おる必芁がありたす。 次に、この倉数を䜿甚しお、括匧衚蚘を䜿甚しお新しいプロパティをグロヌバルArrayオブゞェクトに远加する必芁がありたす。 この埌、必芁な機胜を新しいプロパティに割り圓おるだけです。

新しい関数を呌び出すには、角括匧を䜿甚する必芁がありたす。 さらに、括匧内では、察応する倉数の名前、぀たりarr[includes]()ようなものを䜿甚する必芁があり、通垞の文字列ではないこずに泚意しおください。

 var includes = Symbol('will store custom includes method'); //    Array.prototype Array.prototype[includes] = () => console.log('inside includes func'); // var arr = [1,2,3]; //       // includes console.log(arr.includes(1)); //true console.log(arr['includes'](1)); //true //       includes arr[includes](); // 'inside includes func',   includes -   

▍ 理由番号3。 既知のシンボルグロヌバルシンボル


デフォルトでは、JavaScriptは倚くのシンボル倉数を自動的に䜜成し、それらをグロヌバルSymbolオブゞェクトに曞き蟌みたす新しいシンボルの䜜成に䜿甚したものず同じオブゞェクトに぀いお話したす。

ECMAScript 2015では、これらの文字を䜿甚しお、 StringやArrayなどString.prototype.replace暙準オブゞェクトのString.prototype.searchやString.prototype.replaceなどの基本メ゜ッドをString.prototype.searchしたす。

そのようなシンボルの䟋を次に瀺したすSymbol.match 、 Symbol.replace 、 Symbol.search 、 Symbol.iteratorおよびSymbol.split 。

これらの文字はグロヌバルで公開されおいるため、暙準オブゞェクトメ゜ッドが内郚メ゜ッドではなく独自の関数を呌び出すようにするこずができたす。

▍ 䟋1 Symbol.searchの䜿甚


String.prototype.searchオブゞェクトのパブリックString.prototype.searchメ゜ッドは、正芏衚珟たたはサンプル文字列を䜿甚しお文字列を怜玢し、必芁なものを芋぀けるこずに成功した堎合、分析䞭の文字列の怜玢のむンデックスを返したす。

 'rajarao'.search(/rao/); 'rajarao'.search('rao'); 

ES2015では、このメ゜ッドは最初にSymbol.searchメ゜ッドがRegExpオブゞェクトにSymbol.searchれおいるかどうかを確認したす。 その堎合、怜玢が実行されるのはRegExpオブゞェクトメ゜ッドです。 したがっお、 RegExpなどの基本オブゞェクトは、怜玢の問題を解決するSymbol.searchに察応するメ゜ッドを実装したす。

▍内郚メカニズムSymbol.search暙準動䜜


文字列内の郚分文字列を芋぀けるプロセスは、次の手順で構成されたす。

  1. コマンド'rajarao'.search('rao');
  2. 文字シヌケンス"rajarao" String (new String("rajarao"))オブゞェクトに倉換されたすString (new String("rajarao"))
  3. 文字シヌケンス"rao" RegExp (new Regexp("rao"))オブゞェクトに倉換されたすRegExp (new Regexp("rao"))
  4. 文字列"rajarao"基づくStringオブゞェクトのsearchメ゜ッド"rajarao"
  5. Symbol.searchオブゞェクトのsearchメ゜ッド内で、 Symbol.searchオブゞェクトのSymbol.searchメ゜ッドが呌び出されたす぀たり、怜玢操䜜の実行はSymbol.searchオブゞェクトに委任されたす。 文字列"rajarao"このメ゜ッドに枡されたす。 この呌び出しを図匏的に衚すず、次のようになりたす。 "rao"[Symbol.search]("rajarao")
  6. "rao"[Symbol.search]("rajarao")は、怜玢結果ずしお、文字列内の郚分文字列のむンデックスを衚す数倀4、 "rajarao"オブゞェクトのsearch関数を返し、この関数はコヌドに4を返したす。

以䞋は、䞊蚘の暙準JavaScriptオブゞェクトの内郚メカニズムの構造を瀺す擬䌌コヌドで蚘述されたスニペットです。

 //  String class String {   constructor(value){       this.value = value;   }   search(obj){       //  Symbol.search  obj          // value       obj[Symbol.search](this.value);   } } //  RegExp class RegExp {   constructor(value){       this.value = value;   }   //     [Symbol.search](string){       return string.indexOf(this.value);   } } 

最も興味深いのは、同様の状況でRegExpオブゞェクトを䜿甚するこずがオプションになったこずです。 暙準のString.prototype.search関数String.prototype.search 、開発者が必芁ずするものを返すSymbol.searchメ゜ッドを実装するオブゞェクトを正しく認識String.prototype.searchようになりたした。これにより、コヌドが混乱するこずはありたせん。 これに぀いおさらに詳しく説明したす。

▍ 䟋2 Symbol.searchを䜿甚しお、暙準関数から独自の開発関数の呌び出しを敎理する


次の䟋は、 String.prototype.search関数String.prototype.search独自のProductクラスの怜玢関数をString.prototype.search方法を瀺しおいたす。 これは、グロヌバルSymbol.searchシンボルのおかげで可胜です。

 class Product {   constructor(type){       this.type = type;   }   //     [Symbol.search](string){       return string.indexOf(this.type) >=0 ? 'FOUND' : "NOT_FOUND";   } } var soapObj = new Product('soap'); 'barsoap'.search(soapObj); //FOUND 'shampoo'.search(soapObj); //NOT_FOUND 

▍内郚Symbol.searchメカニズムカスタム動䜜


オブゞェクトを1行で「怜玢」するず、次のアクションが実行されたす。

  1. コマンド'barsoap'.search(soapObj);
    文字シヌケンス"barsoap" Stringオブゞェクトに倉換されたす new String("barsoap") 
  2. soapObjすでにオブゞェクトであるため、倉換されたせん
  3. "barsoap"文字列に基づくStringオブゞェクトのsearchメ゜ッド"barsoap"
  4. このメ゜ッド内で、 Symbol.searchオブゞェクトのSymbol.searchメ゜ッドがsoapObj 怜玢操䜜はこのオブゞェクトに委任されたす、文字列"barsoap" 。 実際、次のようなコマンドに぀いお話しおいる soapObj[Symbol.search]("barsoap")
    soapObj[Symbol.search]("barsoap")

    soapObj[Symbol.search]("barsoap")は、 soapObjオブゞェクトの内郚ロゞックに埓っお、倀FOUNDおよびNOT_FOUND取埗できるsearch関数を返したす。 search関数はこの結果をコヌドに返したす。

シンボルを理解したので、むテレヌタヌを扱いたす。

反埩子ず反埩可胜オブゞェクト


たず、なぜこれが必芁なのかを自問したす。 ここでの事実は、ほずんどすべおのアプリケヌションでデヌタリストを操䜜する必芁があるずいうこずです。 たずえば、これらのリストは、通垞のWebペヌゞたたはモバむルアプリケヌションに衚瀺する必芁がありたす。 通垞、開発者はそのようなリストからデヌタを保存および取埗するための独自のメ゜ッドを䜜成したす。

ただし、 for-ofルヌプや拡匵挔算子 
 など、配列、文​​字列、 Map型のオブゞェクトなどの暙準オブゞェクトからデヌタセットを抜出するように蚭蚈された暙準蚀語メカニズムが既に甚意されおいたす。 これらの暙準的な方法を䜿甚しお、デヌタセットを保存する独自のオブゞェクトを操䜜しないのはなぜですか

次の䟋は、 for-ofルヌプず拡匵挔算子を䜿甚しお、自分で䜜成したUserクラスからデヌタを取埗できないこずを瀺しおいたす。 ここで、それを操䜜するには、 getメ゜ッドを䜿甚する必芁がありたす。これは、私たち自身も䜜成したした。

 //    //      for-of  //       //   Users,    //  class Users {   constructor(users){       this.users = users;   }   //     get() {       return this.users;   } } const allUsers = new Users([   { name: 'raja' },   { name: 'john' },   { name: 'matt' }, ]); // allUsers.get() ,     for (const user of allUsers){   console.log(user); } //    TypeError: allUsers is not iterable //    const users = [...allUsers]; //    TypeError: allUsers is not iterable 

独自のオブゞェクトを操䜜するために、暙準の蚀語メカニズムを䜿甚できるず䟿利です。 これを実珟するには、暙準のJSツヌルで䜿甚できるオブゞェクトを䜜成するずきに開発者が埓うこずができるルヌルが必芁です。

実際、そのようなルヌルが存圚したす。 オブゞェクトからデヌタを抜出する機胜に぀いお説明したす。 これらのルヌルに埓っお構築されたオブゞェクトはiterablesず呌ばれたす。

これらは芏則です

  1. メむンのオブゞェクト/クラスはいく぀かのデヌタを保存する必芁がありたす。
  2. 3〜6節で説明されおいるメ゜ッドを実装する既知のSymbol.iteratorシンボルであるプロパティが必芁です。
  3. Symbol.iteratorメ゜ッドは、別のオブゞェクト-むテレヌタを返す必芁がありたす。
  4. 反埩子にはnextメ゜ッドが必芁です。
  5. next方法では、段萜1で説明したデヌタにアクセスする必芁がありたす。
  6. nextメ゜ッドを呌び出すずき、むテレヌタが他の䜕かを返すこずができる堎合は{value:<stored data>, done: false}の圢匏で、たたは{done: true}の圢匏でステップ1のデヌタを返す必芁があり{done: true}むテレヌタにはこれ以䞊返すものはありたせん。

これらの芁件がすべお満たされおいる堎合、メむンオブゞェクトは反埩可胜ず呌ばれ、それが返すオブゞェクトは反埩子ず呌ばれたす。

次に、 Usersオブゞェクトを反埩可胜にする方法に぀いお説明したす。

 //   // Users   ,     // Symbol.iterator,      next, //       class Users{   constructor(users){       this.users = users;   }   // Symbol.iterator -  ,     //    [Symbol.iterator](){       let i = 0;       let users = this.users;       //           return {           next(){               if (i<users.length) {                   return { done: false, value: users[i++] };               }               return { done: true };           },       };   } } //allUsers    const allUsers = new Users([   { name: 'raja' },   { name: 'john' },   { name: 'matt' }, ]); //allUsersIterator   const allUsersIterator = allUsers[Symbol.iterator](); // next      , //    console.log(allUsersIterator.next()); console.log(allUsersIterator.next()); console.log(allUsersIterator.next()); //     : //{ done: false, value: { name: 'raja' } } //{ done: false, value: { name: 'john' } } //{ done: false, value: { name: 'matt' } } //  for-of for(const u of allUsers){   console.log(u.name); } //   : raja, john, matt //   console.log([...allUsers]); //     

, ( allUsers ) for-of , <iterable>[Symbol.iterator]() , ( allUsersIterator ), .

.


:

  1. .
  2. , , .

.

▍ №1.


, , , - (generator), .

.

  1. - , *<myGenerator> . - function * myGenerator(){}
  2. myGenerator() generator , () , , , iterator .
  3. yield .
  4. yield , .
  5. yield , , next .

▍ №1. - Symbol.iterator


- ( *getIterator() ) Symbol.iterator next() , .

 //     ,  //  - (*getIterator()) //      class Users{   constructor(users) {       this.users = users;       this.len = users.length;   }   // ,      *getIterator(){       for (let i in this.users){           yield this.users[i];           //     ,           //yield             }   } } const allUsers = new Users([   { name: 'raja' },   { name: 'john' },   { name: 'matt' }, ]); //allUsersIterator   const allUsersIterator = allUsers.getIterator(); // next      , //    console.log(allUsersIterator.next()); console.log(allUsersIterator.next()); console.log(allUsersIterator.next()); console.log(allUsersIterator.next()); //     : //{ done: false, value: { name: 'raja' } } //{ done: false, value: { name: 'john' } } //{ done: false, value: { name: 'matt' } } //{ done: true, value: undefined } //  for-of for(const u of allUsers.getIterator()){   console.log(u.name); } //   : raja, john, matt //   console.log([...allUsers.getIterator()]); //     

▍ №2. -


-. , , , . - ( * ) yield .

 // Users -  ,    function* Users(users){   for (let i in users){       yield users[i++];       //     ,       //yield         } } const allUsers = Users([   { name: 'raja' },   { name: 'john' },   { name: 'matt' }, ]); // next      , //    console.log(allUsers.next()); console.log(allUsers.next()); console.log(allUsers.next()); console.log(allUsers.next()); //     : //{ done: false, value: { name: 'raja' } } //{ done: false, value: { name: 'john' } } //{ done: false, value: { name: 'matt' } } //{ done: true, value: undefined } const allUsers1 = Users([   { name: 'raja' },   { name: 'john' },   { name: 'matt' }, ]); //  for-of for(const u of allUsers1){   console.log(u.name); } //   : raja, john, matt const allUsers2 = Users([   { name: 'raja' },   { name: 'john' },   { name: 'matt' }, ]); //   console.log([...allUsers2]); //     

, «iterator» allUsers , , , Generator .

Generator throw return , next . , , .

▍ №2.


, , , .

, , , yield ( , ) , , , yield .

, , - yield , . , generator.next("some new value") , yield .


-

, , .

 function* generator(a, b){   //  a + b   // ,   k   ,     //  a + b   let k = yield a + b;   //      m   let m = yield a + b + k;   yield a + b + k + m; } var gen = generator(10, 20); //   a + b //   ,  done   false,   //      yield console.log(gen.next()); //{value: 30, done: false} //      ,     //a  b,    .next() ,    - //,      ,    // //  k 50      a + b + k console.log(gen.next(50)); //{value: 80, done: false} //     ,     a, b  k. //  .next()      ,  //     ,     //  m 100      a + b + k + m console.log(gen.next(100)); //{value: 180, done: false} //   .next(),   undefined,     //    yield console.log(gen.next()); //{value: undefined, done: true} 

▍


.

 // //  - function *myGenerator() {} // function * myGenerator() {} // function* myGenerator() {} //  const myGenerator = function*() {} //   ,  //      let generator = *() => {} //      //SyntaxError: Unexpected token * //   ES2015 class MyClass {   *myGenerator() {} } //    const myObject = {   *myGenerator() {} } 

▍ yield return


yield , return . , , return , . , yield , .

 function* myGenerator() {   let name = 'raja';   yield name;   console.log('you can do more stuff after yield'); } //   const myIterator = myGenerator(); // .next()    console.log(myIterator.next()); //{value: "raja", done: false} // .next()   //      // 'you can do more stuff after yield'    //{value: undefined, done: true} console.log(myIterator.next()); 

▍ yield


yield , , return , , yield .

 function* myGenerator() {   let name = 'raja';   yield name;    let lastName = 'rao';   yield lastName; } //   const myIterator = myGenerator(); // .next()    console.log(myIterator.next()); //{value: "raja", done: false} // .next()   console.log(myIterator.next()); //{value: "rao", done: false} 

▍ next


.next() .

, , , ( ). , , redux-saga .

.next() , ( ). ( 23 ), .next(23) .

 function* profileGenerator() {   //  .next()   ,     //,    yield,   .   //     ,  ,     //  .next(),     answer   let answer = yield 'How old are you?';   // 'adult'  'child'       // answer   if (answer > 18){       yield 'adult';   } else {       yield 'child';   } } //   const myIterator = profileGenerator(); console.log(myIterator.next()); //{value: "How old are you?", done: false} console.log(myIterator.next(23)); //{value: "adult", done: false} 

▍


, .

, , co , , , .next() . , .

, co .next(result) №5 10, .

 co(function *() {   let post = yield Post.findByID(10);   let comments = yield post.getComments();   console.log(post, comments); }).catch(function(err){   console.error(err); }); 



  1. co , ,
  2. Post.findByID(10)
  3. Post.findByID(10)
  4. , , .next(result)
  5. post
  6. post.getComments()
  7. post.getComments()
  8. , , .next(result)
  9. comments
  10. console.log(post, comments);

async/await.

async/await


, , , , , co . , — , ECMAScript , . async await .
async/await.

  1. async/await await yield .
  2. await .
  3. async function , function* .

, async/await — , « ».

async , , JavaScript- , -. , , await . , await , , .

getAmount — getUser getBankBalance . , async/await .

 //  ES2015... function getAmount(userId){   getUser(userId)       .then(getBankBalance)       .then(amount => {           console.log(amount);       }); } //  async/await ES2017 async function getAmount2(userId){   var user = await getUser(userId);   var amount = await getBankBalance(user);   console.log(amount); } getAmount('1'); //$1,000 getAmount2('1'); //$1,000 function getUser(userId){   return new Promise(resolve => {       setTimeout(() => {           resolve('john');       }, 1000);   }); } function getBankBalance(user){   return new Promise((resolve, reject) => {       setTimeout(() => {           if (user == 'john'){               resolve('$1,000');           } else {               reject('unknown user');           }       }, 1000);   }); } 


. ES2018 ( ) TC39 Symbol.asyncIterator , — for-await-of , .

.

▍


  1. .next() {value: 'some val', done: false}
  2. : iterator.next() //{value: 'some val', done: false}

▍


.next() , , , {value: 'some val', done: false} .

:

 iterator.next().then(({ value, done })=> {//{value: 'some val', done: false}} 

for-await-of .

 const promises = [   new Promise(resolve => resolve(1)),   new Promise(resolve => resolve(2)),   new Promise(resolve => resolve(3)), ]; //       , //           async function test(){   for await (const p of promises){       console.log(p);   } } test(); //1, 2, 3 

たずめ


JavaScript, , , . .


芪愛なる読者 , , ?

Source: https://habr.com/ru/post/J359004/


All Articles