技术控

    今日:0| 主题:63445
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] ES6 Iterators and Generators: 6 Exercises and Solutions

[复制链接]
残梦Dangerou 发表于 2016-11-28 08:34:44
138 3
This article is a section from the workbook of ES6 in Practice. I created this course during the last couple of months, because there is an evident need for a resource that helps JavaScript developers put theory into practice.
  This course won’t waste your time with long hours of video, or long pages of theory that you will never use in practice. We will instead focus on learning just enough theory to solve some exercises. Once you are done with the exercises, you can check the reference solutions, and conclude some lessons. In fact, some of the theory are sometimes placed in the reference solutions.
  If you like this article, check out the course    here.  
  In mylast article, I gave you six exercises. Today, you can check the reference solution.  
  Exercise 1.What happens if we use a string iterator instead of an iterable object in a    for-ofloop?  
  1.  
  2. letmessage = 'ok';
  3. letmessageIterator = message[Symbol.iterator]();
  4.  
  5. messageIterator.next();
  6.  
  7. for ( letitemofmessageIterator ) {
  8.     console.log( item );
  9. }
  10.  
复制代码
Solution:Similarly to generators, in case of strings, arrays, DOM elements, sets, and maps, an iterator object is also an iterable.  
  Therefore, in the    for-ofloop, the remaining    kletter is printed out.  
  Exercise 2.Create a countdown iterator that counts from 9 to 1. Use generator functions!  
  1.  
  2. letgetCountdownIterator = // Your code comes here
  3.  
  4. console.log( [ ...getCountdownIterator() ] );
  5. > [9, 8, 7, 6, 5, 4, 3, 2, 1]
  6.  
复制代码
Solution:

  1.  
  2. letgetCountdownIterator = function *() {
  3.     let i = 10;
  4.     while( i > 1 ) {
  5.         yield --i;
  6.     }
  7. }
  8.  
  9. console.log( [ ...getCountdownIterator() ] );
  10. > [9, 8, 7, 6, 5, 4, 3, 2, 1]
  11.  
复制代码
The generator function yields the numbers    9to    1. The spread (    ...) operator consumes all values. Then the generator function returns    undefined, ending the iteration process.  
  Exercise 3.Make the following object iterable:  
  1.  
  2. lettodoList = {
  3.     todoItems: [],
  4.     addItem( description ) {
  5.         this.todoItems.push( { description, done: false } );
  6.         return this;
  7.     },
  8.     crossOutItem( index ) {
  9.         if ( index < this.todoItems.length ) {
  10.             this.todoItems[index].done = true;
  11.         }
  12.         return this;
  13.     }
  14. };
  15.  
  16. todoList.addItem( 'task 1' ).addItem( 'task 2' ).crossOutItem( 0 );
  17.  
  18. letiterableTodoList = // ???;
  19.  
  20. for ( letitemofiterableTodoList ) {
  21.     console.log( item );
  22. }
  23.  
  24. // Without your code, you get the following error:
  25. // Uncaught TypeError: todoList[Symbol.iterator] is not a function
  26.  
复制代码
First Solution (well known symbol):

  We could use well known symbols to make    todoListiterable. We can add a    *[Symbol.iterator]generator function that yields the elements of the array. This will make the    todoListobject iterable, yielding the elements of    todoItemsone by one.  
  1.  
  2. lettodoList = {
  3.     todoItems: [],
  4.     *[Symbol.iterator]() {
  5.         yield* this.todoItems;
  6.     }
  7.     addItem( description ) {
  8.         this.todoItems.push( { description, done: false } );
  9.         return this;
  10.     },
  11.     crossOutItem( index ) {
  12.         if ( index < this.todoItems.length ) {
  13.             this.todoItems[index].done = true;
  14.         }
  15.         return this;
  16.     }
  17. };
  18.  
  19. letiterableTodoList = todoList;
  20.  
复制代码
Second solution (generator function): If you prefer staying away from well known symbols, it is possible to make your code more semantic:  
  1.  
  2. lettodoList = {
  3.     todoItems: [],
  4.     addItem( description ) {
  5.         this.todoItems.push( { description, done: false } );
  6.         return this;
  7.     },
  8.     crossOutItem( index ) {
  9.         if ( index < this.todoItems.length ) {
  10.             this.todoItems[index].done = true;
  11.         }
  12.         return this;
  13.     }
  14. };
  15.  
  16. todoList.addItem( 'task 1' ).addItem( 'task 2' ).crossOutItem( 0 );
  17.  
  18. lettodoListGenerator = function *() {
  19.     yield* todoList.todoItems;
  20. }
  21.  
  22. letiterableTodoList = todoListGenerator();
  23.  
复制代码
The first solution reads a bit like a hack. The second solution looks cleaner even if you have to type more characters.
  Exercise 4.Determine the values logged to the console without running the code. Instead of just writing down the values, formulate your thought process and explain to yourself how the code runs line by line.  
  1.  
  2. leterrorDemo = function *() {
  3.     yield 1;
  4.     throw 'Error yielding the next result';
  5.     yield 2;
  6. }
  7.  
  8. letit = errorDemo();
  9.  
  10. // Execute one statement at a time to avoid
  11. // skipping lines after the first thrown error.
  12.  
  13. console.log( it.next() );
  14.  
  15. console.log( it.next() );
  16.  
  17. console.log( [...errorDemo()] );
  18.  
  19. for ( letelementoferrorDemo() ) {
  20.     console.log( element );
  21. }
  22.  
复制代码
Solution:

  1.  
  2. console.log( it.next() );
  3. > Object {value: 1, done: false}
  4.  
  5. console.log( it.next() );
  6. > UncaughtErroryieldingthenextresult
  7.  
  8. console.log( [...errorDemo()] );
  9. > UncaughtErroryieldingthenextresult
  10.  
  11. for ( letelementoferrorDemo() ) {
  12.     console.log( element );
  13. }
  14. > Object {value: 1, done: false}
  15. > UncaughtErroryieldingthenextresult
  16.  
复制代码
We created three iterables in total:    it, one in the statement in the spread operator, and one in the    for-ofloop.  
  In the example with the    nextcalls, the second call results in a thrown error.  
  In the spread operator example, the expression cannot be evaluated, because an error is thrown.
  In the    for-ofexample, the first element is printed out, then the error stopped the execution of the loop.  
  Exercise 5.Create an infinite sequence that generates the next value of the Fibonacci sequence.  
  The Fibonacci sequence is defined as follows:
  
       
  •       fib( 0 ) = 0   
  •       fib( 1 ) = 1   
  • for      n > 1,      fib( n ) = fib( n - 1 ) + fib( n - 2 )  
  Solution:

  1.  
  2. function *fibonacci() {
  3.     let a = 0, b = 1;
  4.     yield a;
  5.     yield b;
  6.     while( true ) {
  7.         [a, b] = [b, a+b];
  8.         yield b;
  9.     }
  10. }
  11.  
复制代码
Note that you only want to get the    next()element of an infinite sequence. Executing    [...fibonacci()]will skyrocket your CPU usage, speed up your CPU fan, and then crash your browser.  
  Exercise 6.Create a lazy    filtergenerator function. Filter the elements of the Fibonacci sequence by keeping the even values only.  
  1.  
  2. function *filter( iterable, filterFunction ) {
  3.     // insert code here
  4. }
  5.  
复制代码
Solution:

  1.  
  2. letgetCountdownIterator = // Your code comes here
  3.  
  4. console.log( [ ...getCountdownIterator() ] );
  5. > [9, 8, 7, 6, 5, 4, 3, 2, 1]
  6.  
  7. 0
复制代码
Notice how easy it is to combine generators and lazily evaluate them.
  1.  
  2. letgetCountdownIterator = // Your code comes here
  3.  
  4. console.log( [ ...getCountdownIterator() ] );
  5. > [9, 8, 7, 6, 5, 4, 3, 2, 1]
  6.  
  7. 1
复制代码
Lazy evaluation is essential when we work on a large set of data. For instance, if you have 1000 accounts, chances are that you don’t want to transform all of them if you just want to render the first ten on screen. This is when lazy evaluation comes into play.
刘徐 发表于 2016-11-28 12:29:57
沙发不是你想抢,想抢就能抢!
回复 支持 反对

使用道具 举报

feixiang222 发表于 2016-11-28 17:11:21
不要羡慕,不要崇拜,更不要粉我,feixiang222不是归人,只是过客
回复 支持 反对

使用道具 举报

林厚磊 发表于 2016-12-24 23:52:06
喜欢的摇,不喜欢的滚。
回复 支持 反对

使用道具 举报

我要投稿

推荐阅读


回页顶回复上一篇下一篇回列表
手机版/c.CoLaBug.com ( 粤ICP备05003221号 | 粤公网安备 44010402000842号 )

© 2001-2017 Comsenz Inc.

返回顶部 返回列表