Skip to content

Commit 6bf087c

Browse files
committed
edit set
1 parent f69843a commit 6bf087c

File tree

5 files changed

+59
-80
lines changed

5 files changed

+59
-80
lines changed

docs/function.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,21 +413,17 @@ const [first, ...middle, last] = [1, 2, 3, 4, 5];
413413
JavaScript的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。
414414

415415
```javascript
416-
417416
var dateFields = readDateFields(database);
418417
var d = new Date(...dateFields);
419-
420418
```
421419

422420
上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数Date。
423421

424422
除了展开数组,扩展运算符还可以将一个数值扩展成数组。
425423

426424
```javascript
427-
428425
[...5]
429426
// [0, 1, 2, 3, 4, 5]
430-
431427
```
432428

433429
扩展运算符还可以将字符串转为真正的数组。

docs/generator.md

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@
77
在形式上,Generator是一个普通函数,但是有两个特征。一是,function命令与函数名之间有一个星号;二是,函数体内部使用yield语句,定义遍历器的每个成员,即不同的内部状态(yield语句在英语里的意思就是“产出”)。
88

99
```javascript
10-
1110
function* helloWorldGenerator() {
1211
yield 'hello';
1312
yield 'world';
1413
return 'ending';
1514
}
1615

1716
var hw = helloWorldGenerator();
18-
1917
```
2018

2119
上面代码定义了一个Generator函数helloWorldGenerator,它的遍历器有两个成员“hello”和“world”。调用这个函数,就会得到遍历器。
@@ -127,7 +125,6 @@ for (var f of flat(arr)){
127125
上面代码也会产生句法错误,因为forEach方法的参数是一个普通函数,但是在里面使用了yield语句。一种修改方法是改用for循环。
128126
129127
```javascript
130-
131128
var arr = [1, [[2, 3], 4], [5, 6]];
132129

133130
var flat = function* (a){
@@ -146,15 +143,13 @@ for (var f of flat(arr)){
146143
console.log(f);
147144
}
148145
// 1, 2, 3, 4, 5, 6
149-
150146
```
151147
152148
## next方法的参数
153149
154150
yield语句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。
155151
156152
```javascript
157-
158153
function* f() {
159154
for(var i=0; true; i++) {
160155
var reset = yield i;
@@ -167,7 +162,6 @@ var g = f();
167162
g.next() // { value: 0, done: false }
168163
g.next() // { value: 1, done: false }
169164
g.next(true) // { value: 0, done: false }
170-
171165
```
172166
173167
上面代码先定义了一个可以无限运行的Generator函数f,如果next方法没有参数,每次运行到yield语句,变量reset的值总是undefined。当next方法带一个参数true时,当前的变量reset就被重置为这个参数(即true),因此i会等于-1,下一轮循环就会从-1开始递增。
@@ -177,7 +171,24 @@ g.next(true) // { value: 0, done: false }
177171
再看一个例子。
178172
179173
```javascript
174+
function* foo(x) {
175+
var y = 2 * (yield (x + 1));
176+
var z = yield (y / 3);
177+
return (x + y + z);
178+
}
179+
180+
var a = foo(5);
180181

182+
a.next() // Object{value:6, done:false}
183+
a.next() // Object{value:NaN, done:false}
184+
a.next() // Object{value:NaN, done:false}
185+
```
186+
187+
上面代码中,第二次运行next方法的时候不带参数,导致y的值等于`2 * undefined`(即NaN),除以3以后还是NaN,因此返回对象的value属性也等于NaN。第三次运行Next方法的时候不带参数,所以z等于undefined,返回对象的value属性等于`5 + NaN + undefined`,即NaN。
188+
189+
如果向next方法提供参数,返回结果就完全不一样了。
190+
191+
```javascript
181192
function* foo(x) {
182193
var y = 2 * (yield (x + 1));
183194
var z = yield (y / 3);
@@ -192,7 +203,6 @@ it.next(12)
192203
// { value:8, done:false }
193204
it.next(13)
194205
// { value:42, done:true }
195-
196206
```
197207
198208
上面代码第一次调用next方法时,返回`x+1`的值6;第二次调用next方法,将上一次yield语句的值设为12,因此y等于24,返回`y / 3`的值8;第三次调用next方法,将上一次yield语句的值设为13,因此z等于13,这时x等于5,y等于24,所以return语句的值等于42。
@@ -249,15 +259,12 @@ for (let n of fibonacci()) {
249259
Generator函数还有一个特点,它可以在函数体外抛出错误,然后在函数体内捕获。
250260
251261
```javascript
252-
253262
var g = function* () {
254263
while (true) {
255264
try {
256265
yield;
257266
} catch (e) {
258-
if (e != 'a') {
259-
throw e;
260-
}
267+
if (e != 'a') throw e;
261268
console.log('内部捕获', e);
262269
}
263270
}
@@ -274,7 +281,6 @@ try {
274281
}
275282
// 内部捕获 a
276283
// 外部捕获 b
277-
278284
```
279285
280286
上面代码中,遍历器i连续抛出两个错误。第一个错误被Generator函数体内的catch捕获,然后Generator函数执行完成,于是第二个错误被函数体外的catch捕获。
@@ -287,9 +293,7 @@ var g = function* () {
287293
try {
288294
yield;
289295
} catch (e) {
290-
if (e != 'a') {
291-
throw e;
292-
}
296+
if (e != 'a') throw e;
293297
console.log('内部捕获', e);
294298
}
295299
}
@@ -436,52 +440,51 @@ try {
436440
437441
上面代码中,第二个next方法向函数体内传入一个参数42,数值是没有toUpperCase方法的,所以会抛出一个TypeError错误,被函数体外的catch捕获。
438442
439-
一旦Generator执行过程中抛出错误,就不会再执行下去了。如果此后还调用next方法,将一直返回发生错误前的那个值
443+
一旦Generator执行过程中抛出错误,就不会再执行下去了。如果此后还调用next方法,将返回一个value属性等于undefined、done属性等于true的对象,即JavaScript引擎认为这个Generator已经运行结束了
440444
441445
```javascript
442-
443446
function* g() {
444447
yield 1;
445448
console.log('throwing an exception');
446449
throw new Error('generator broke!');
447450
yield 2;
451+
yield 3;
448452
}
449453

450454
function log(generator) {
451455
var v;
452456
console.log('starting generator');
453457
try {
454458
v = generator.next();
455-
console.log('got back', v);
459+
console.log('第一次运行next方法', v);
456460
} catch (err) {
457-
console.log('fixing generator', v);
461+
console.log('捕捉错误', v);
458462
}
459463
try {
460464
v = generator.next();
461-
console.log('got back', v);
465+
console.log('第二次运行next方法', v);
462466
} catch (err) {
463-
console.log('fixing generator', v);
467+
console.log('捕捉错误', v);
464468
}
465469
try {
466470
v = generator.next();
467-
console.log('got back', v);
471+
console.log('第三次运行next方法', v);
468472
} catch (err) {
469-
console.log('fixing generator', v);
473+
console.log('捕捉错误', v);
470474
}
471475
console.log('caller done');
472476
}
473477

474478
log(g());
475479
// starting generator
476-
// got back { value: 1, done: false }
480+
// 第一次运行next方法 { value: 1, done: false }
477481
// throwing an exception
478-
// fixing generator { value: 1, done: false }
479-
// fixing generator { value: 1, done: false }
482+
// 捕捉错误 { value: 1, done: false }
483+
// 第三次运行next方法 { value: undefined, done: true }
480484
// caller done
481-
482485
```
483486
484-
上面代码在Generator函数g抛出错误以后,再调用next方法,就不再执行下去了,一直停留在上一次的状态
487+
上面代码一共三次运行next方法,第二次运行的时候会抛出错误,然后第三次运行的时候,Generator函数就已经结束了,不再执行下去了
485488
486489
## yield*语句
487490

docs/let.md

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,58 +7,50 @@
77
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
88

99
```javascript
10-
1110
{
1211
let a = 10;
1312
var b = 1;
1413
}
1514

1615
a // ReferenceError: a is not defined.
1716
b // 1
18-
1917
```
2018

2119
上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。
2220

2321
for循环的计数器,就很合适使用let命令。
2422

2523
```javascript
26-
2724
for(let i = 0; i < arr.length; i++){}
2825

2926
console.log(i)
3027
//ReferenceError: i is not defined
31-
3228
```
3329

3430
上面代码的计数器i,只在for循环体内有效。
3531

3632
下面的代码如果使用var,最后输出的是10。
3733

3834
```javascript
39-
4035
var a = [];
4136
for (var i = 0; i < 10; i++) {
4237
a[i] = function () {
4338
console.log(i);
4439
};
4540
}
4641
a[6](); // 10
47-
4842
```
4943

5044
如果使用let,声明的变量仅在块级作用域内有效,最后输出的是6。
5145

5246
```javascript
53-
5447
var a = [];
5548
for (let i = 0; i < 10; i++) {
5649
a[i] = function () {
5750
console.log(i);
5851
};
5952
}
6053
a[6](); // 6
61-
6254
```
6355

6456
### 不存在变量提升
@@ -370,20 +362,18 @@ var constantize = (obj) => {
370362

371363
## 全局对象的属性
372364

373-
全局对象是最顶层的对象,在浏览器环境指的是window对象,在Node.js指的是global对象。ES5规定,所有全局变量都是全局对象的属性。
365+
全局对象是最顶层的对象,在浏览器环境指的是window对象,在Node.js指的是global对象。在JavaScript语言中,所有全局变量都是全局对象的属性。
374366

375367
ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性;let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。
376368

377369
```javascript
378-
379370
var a = 1;
380371
// 如果在node环境,可以写成global.a
381372
// 或者采用通用方法,写成this.a
382373
window.a // 1
383374

384375
let b = 1;
385376
window.b // undefined
386-
387377
```
388378

389379
上面代码中,全局变量a由var命令声明,所以它是全局对象的属性;全局变量b由let命令声明,所以它不是全局对象的属性,返回undefined。

0 commit comments

Comments
 (0)