@@ -94,7 +94,7 @@ setTimeout(function () {
94
94
}, 2000 );
95
95
```
96
96
97
- 上面代码中,函数f如果是普通函数 ,在为变量generator赋值时就会执行。但是,函数f是一个Generator函数,就变成只有调用next方法时,函数f才会执行 。
97
+ 上面代码中,函数 ` f ` 如果是普通函数 ,在为变量generator赋值时就会执行。但是,函数 ` f ` 是一个Generator函数,就变成只有调用 ` next ` 方法时,函数 ` f ` 才会执行 。
98
98
99
99
另外需要注意,yield语句不能用在普通函数中,否则会报错。
100
100
@@ -246,7 +246,7 @@ it.next(13)
246
246
// { value:42, done:true }
247
247
` ` `
248
248
249
- 上面代码第一次调用next方法时 ,返回` x+ 1 ` 的值6;第二次调用` next` 方法,将上一次` yield ` 语句的值设为12,因此` y` 等于24,返回` y / 3 ` 的值8;第三次调用` next` 方法,将上一次` yield ` 语句的值设为13,因此` z` 等于13,这时` x` 等于5,` y` 等于24,所以` return ` 语句的值等于42。
249
+ 上面代码第一次调用 ` next ` 方法时 ,返回` x+ 1 ` 的值6;第二次调用` next` 方法,将上一次` yield ` 语句的值设为12,因此` y` 等于24,返回` y / 3 ` 的值8;第三次调用` next` 方法,将上一次` yield ` 语句的值设为13,因此` z` 等于13,这时` x` 等于5,` y` 等于24,所以` return ` 语句的值等于42。
250
250
251
251
注意,由于` next` 方法的参数表示上一个` yield ` 语句的返回值,所以第一次使用` next` 方法时,不能带有参数。V8引擎直接忽略第一次使用` next` 方法时的参数,只有从第二次使用` next` 方法开始,参数才是有效的。
252
252
@@ -414,7 +414,7 @@ try {
414
414
// 外部捕获 [Error: a]
415
415
` ` `
416
416
417
- 上面代码之所以只捕获了a ,是因为函数体外的catch语句块,捕获了抛出的a错误以后 ,就不会再继续执行try语句块了。
417
+ 上面代码之所以只捕获了 ` a ` ,是因为函数体外的catch语句块,捕获了抛出的 ` a ` 错误以后 ,就不会再继续执行try语句块了。
418
418
419
419
如果Generator函数内部没有部署try...catch代码块,那么throw方法抛出的错误,将被外部try...catch代码块捕获。
420
420
@@ -438,7 +438,7 @@ try {
438
438
// 外部捕获 a
439
439
` ` `
440
440
441
- 上面代码中,遍历器函数g内部 ,没有部署try...catch代码块,所以抛出的错误直接被外部catch代码块捕获。
441
+ 上面代码中,遍历器函数 ` g ` 内部 ,没有部署try...catch代码块,所以抛出的错误直接被外部catch代码块捕获。
442
442
443
443
如果Generator函数内部部署了try...catch代码块,那么遍历器的throw方法抛出的错误,不影响下一次遍历,否则遍历直接终止。
444
444
@@ -682,6 +682,23 @@ function* bar() {
682
682
yield ' y' ;
683
683
}
684
684
685
+ // 等同于
686
+ function * bar () {
687
+ yield ' x' ;
688
+ yield ' a' ;
689
+ yield ' b' ;
690
+ yield ' y' ;
691
+ }
692
+
693
+ // 等同于
694
+ function * bar () {
695
+ yield ' x' ;
696
+ for (let v of foo ()) {
697
+ console .log (v);
698
+ }
699
+ yield ' y' ;
700
+ }
701
+
685
702
for (let v of bar ()){
686
703
console .log (v);
687
704
}
@@ -691,7 +708,39 @@ for (let v of bar()){
691
708
// "y"
692
709
` ` `
693
710
694
- 从另一个角度看,如果` yield ` 命令后面跟的是一个遍历器对象,需要在` yield ` 命令后面加上星号,表明它返回的是一个遍历器对象。这被称为` yield * ` 语句。
711
+ 再来看一个对比的例子。
712
+
713
+ ` ` ` javascript
714
+ function * inner () {
715
+ yield ' hello!' ;
716
+ }
717
+
718
+ function * outer1 () {
719
+ yield ' open' ;
720
+ yield inner ();
721
+ yield ' close' ;
722
+ }
723
+
724
+ var gen = outer1 ()
725
+ gen .next ().value // "open"
726
+ gen .next ().value // 返回一个遍历器对象
727
+ gen .next ().value // "close"
728
+
729
+ function * outer2 () {
730
+ yield ' open'
731
+ yield * inner ()
732
+ yield ' close'
733
+ }
734
+
735
+ var gen = outer2 ()
736
+ gen .next ().value // "open"
737
+ gen .next ().value // "hello!"
738
+ gen .next ().value // "close"
739
+ ` ` `
740
+
741
+ 上面例子中,` outer2` 使用了` yield * ` ,` outer1` 没使用。结果就是,` outer1` 返回一个遍历器对象,` outer2` 返回该遍历器对象的内部值。
742
+
743
+ 从语法角度看,如果` yield ` 命令后面跟的是一个遍历器对象,需要在` yield ` 命令后面加上星号,表明它返回的是一个遍历器对象。这被称为` yield * ` 语句。
695
744
696
745
` ` ` javascript
697
746
let delegatedIterator = (function * () {
@@ -738,49 +787,31 @@ function* concat(iter1, iter2) {
738
787
739
788
上面代码说明,` yield * ` 不过是` for ... of` 的一种简写形式,完全可以用后者替代前者。
740
789
741
- 再来看一个对比的例子 。
790
+ 如果 ` yield * ` 后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员 。
742
791
743
792
` ` ` javascript
744
- function * inner () {
745
- yield ' hello!' ;
746
- }
747
-
748
- function * outer1 () {
749
- yield ' open' ;
750
- yield inner ();
751
- yield ' close' ;
752
- }
753
-
754
- var gen = outer1 ()
755
- gen .next ().value // "open"
756
- gen .next ().value // 返回一个遍历器对象
757
- gen .next ().value // "close"
758
-
759
- function * outer2 () {
760
- yield ' open'
761
- yield * inner ()
762
- yield ' close'
793
+ function * gen (){
794
+ yield * [" a" , " b" , " c" ];
763
795
}
764
796
765
- var gen = outer2 ()
766
- gen .next ().value // "open"
767
- gen .next ().value // "hello!"
768
- gen .next ().value // "close"
797
+ gen ().next () // { value:"a", done:false }
769
798
` ` `
770
799
771
- 上面例子中, ` outer2 ` 使用了 ` yield * ` , ` outer1 ` 没使用。结果就是, ` outer1 ` 返回一个遍历器对象, ` outer2 ` 返回该遍历器对象的内部值 。
800
+ 上面代码中, ` yield ` 命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器对象 。
772
801
773
- 如果 ` yield * ` 后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员 。
802
+ 实际上,任何数据结构只要有Iterator接口,就可以被 ` yield * ` 遍历 。
774
803
775
804
` ` ` javascript
776
- function * gen (){
777
- yield * [" a" , " b" , " c" ];
778
- }
805
+ let read = (function * () {
806
+ yield ' hello' ;
807
+ yield * ' hello' ;
808
+ })();
779
809
780
- gen ().next () // { value:"a", done:false }
810
+ read .next ().value // "hello"
811
+ read .next ().value // "h"
781
812
` ` `
782
813
783
- 上面代码中,` yield ` 命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器对象 。
814
+ 上面代码中,` yield ` 语句返回整个字符串, ` yield * ` 语句返回单个字符。因为字符串具有Iterator接口,所以被 ` yield * ` 遍历 。
784
815
785
816
如果被代理的Generator函数有` return ` 语句,那么就可以向代理它的Generator函数返回数据。
786
817
@@ -840,7 +871,7 @@ for(let x of iterTree(tree)) {
840
871
// e
841
872
` ` `
842
873
843
- 下面是一个稍微复杂的例子,使用yield* 语句遍历完全二叉树。
874
+ 下面是一个稍微复杂的例子,使用 ` yield * ` 语句遍历完全二叉树。
844
875
845
876
` ` ` javascript
846
877
// 下面是二叉树的构造函数,
0 commit comments