Skip to content

Commit 9deab61

Browse files
committed
docs(regex): 新增具名组匹配
1 parent 62a1cd4 commit 9deab61

File tree

4 files changed

+209
-142
lines changed

4 files changed

+209
-142
lines changed

docs/iterator.md

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# Iterator和for...of循环
1+
# Iterator 和 for...of 循环
22

33
## Iterator(遍历器)的概念
44

5-
JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Map的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
5+
JavaScript 原有的表示“集合”的数据结构,主要是数组(`Array`)和对象(`Object`),ES6 又添加了`Map``Set`。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是`Map``Map`的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
66

77
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
88

9-
Iterator的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令`for...of`循环,Iterator接口主要供`for...of`消费。
9+
Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令`for...of`循环,Iterator接口主要供`for...of`消费。
1010

11-
Iterator的遍历过程是这样的
11+
Iterator 的遍历过程是这样的
1212

1313
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
1414

@@ -64,7 +64,7 @@ function makeIterator(array) {
6464
}
6565
```
6666

67-
由于Iterator只是把接口规格加到数据结构之上,所以,遍历器与它所遍历的那个数据结构,实际上是分开的,完全可以写出没有对应数据结构的遍历器对象,或者说用遍历器对象模拟出数据结构。下面是一个无限运行的遍历器对象的例子。
67+
由于 Iterator 只是把接口规格加到数据结构之上,所以,遍历器与它所遍历的那个数据结构,实际上是分开的,完全可以写出没有对应数据结构的遍历器对象,或者说用遍历器对象模拟出数据结构。下面是一个无限运行的遍历器对象的例子。
6868

6969
```javascript
7070
var it = idMaker();
@@ -87,9 +87,7 @@ function idMaker() {
8787

8888
上面的例子中,遍历器生成函数`idMaker`,返回一个遍历器对象(即指针对象)。但是并没有对应的数据结构,或者说,遍历器对象自己描述了一个数据结构出来。
8989

90-
在ES6中,有些数据结构原生具备Iterator接口(比如数组),即不用任何处理,就可以被`for...of`循环遍历,有些就不行(比如对象)。原因在于,这些数据结构原生部署了`Symbol.iterator`属性(详见下文),另外一些数据结构没有。凡是部署了`Symbol.iterator`属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。
91-
92-
如果使用TypeScript的写法,遍历器接口(Iterable)、指针对象(Iterator)和next方法返回值的规格可以描述如下。
90+
如果使用 TypeScript 的写法,遍历器接口(Iterable)、指针对象(Iterator)和`next`方法返回值的规格可以描述如下。
9391

9492
```javascript
9593
interface Iterable {
@@ -106,13 +104,13 @@ interface IterationResult {
106104
}
107105
```
108106

109-
## 数据结构的默认Iterator接口
107+
## 默认 Iterator 接口
110108

111-
Iterator接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即`for...of`循环(详见下文)。当使用`for...of`循环遍历某种数据结构时,该循环会自动去寻找Iterator接口
109+
Iterator 接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即`for...of`循环(详见下文)。当使用`for...of`循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口
112110

113-
一种数据结构只要部署了Iterator接口,我们就称这种数据结构是”可遍历的“(iterable)。
111+
一种数据结构只要部署了 Iterator 接口,我们就称这种数据结构是”可遍历的“(iterable)。
114112

115-
ES6规定,默认的Iterator接口部署在数据结构的`Symbol.iterator`属性,或者说,一个数据结构只要具有`Symbol.iterator`属性,就可以认为是“可遍历的”(iterable)。`Symbol.iterator`属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名`Symbol.iterator`,它是一个表达式,返回`Symbol`对象的`iterator`属性,这是一个预定义好的、类型为Symbol的特殊值,所以要放在方括号内。(参见Symbol一章)。
113+
ES6 规定,默认的 Iterator 接口部署在数据结构的`Symbol.iterator`属性,或者说,一个数据结构只要具有`Symbol.iterator`属性,就可以认为是“可遍历的”(iterable)。`Symbol.iterator`属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名`Symbol.iterator`,它是一个表达式,返回`Symbol`对象的`iterator`属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内(参见 Symbol 一章)。
116114

117115
```javascript
118116
const obj = {
@@ -131,7 +129,18 @@ const obj = {
131129

132130
上面代码中,对象`obj`是可遍历的(iterable),因为具有`Symbol.iterator`属性。执行这个属性,会返回一个遍历器对象。该对象的根本特征就是具有`next`方法。每次调用`next`方法,都会返回一个代表当前成员的信息对象,具有`value``done`两个属性。
133131

134-
在ES6中,有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构。
132+
ES6 的有些数据结构原生具备 Iterator 接口(比如数组),即不用任何处理,就可以被`for...of`循环遍历。原因在于,这些数据结构原生部署了`Symbol.iterator`属性(详见下文),另外一些数据结构没有(比如对象)。凡是部署了`Symbol.iterator`属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。
133+
134+
原生具备 Iterator 接口的数据结构如下。
135+
136+
- Array
137+
- Map
138+
- Set
139+
- String
140+
- TypedArray
141+
- 函数的 arguments 对象
142+
143+
下面的例子是数组的`Symbol.iterator`属性。
135144

136145
```javascript
137146
let arr = ['a', 'b', 'c'];
@@ -145,11 +154,11 @@ iter.next() // { value: undefined, done: true }
145154

146155
上面代码中,变量`arr`是一个数组,原生就具有遍历器接口,部署在`arr``Symbol.iterator`属性上面。所以,调用这个属性,就得到遍历器对象。
147156

148-
上面提到,原生就部署Iterator接口的数据结构有三类,对于这三类数据结构,不用自己写遍历器生成函数,`for...of`循环会自动遍历它们。除此之外,其他数据结构(主要是对象)的Iterator接口,都需要自己在`Symbol.iterator`属性上面部署,这样才会被`for...of`循环遍历。
157+
对于原生部署 Iterator 接口的数据结构,不用自己写遍历器生成函数,`for...of`循环会自动遍历它们。除此之外,其他数据结构(主要是对象)的 Iterator 接口,都需要自己在`Symbol.iterator`属性上面部署,这样才会被`for...of`循环遍历。
149158

150-
对象(Object)之所以没有默认部署Iterator接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。不过,严格地说,对象部署遍历器接口并不是很必要,因为这时对象实际上被当作Map结构使用,ES5没有Map结构,而ES6原生提供了
159+
对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。不过,严格地说,对象部署遍历器接口并不是很必要,因为这时对象实际上被当作Map结构使用,ES5 没有 Map 结构,而 ES6 原生提供了
151160

152-
一个对象如果要有可被`for...of`循环调用的Iterator接口,就必须在`Symbol.iterator`的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
161+
一个对象如果要具备可被`for...of`循环调用的 Iterator 接口,就必须在`Symbol.iterator`的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
153162

154163
```javascript
155164
class RangeIterator {
@@ -175,11 +184,11 @@ function range(start, stop) {
175184
}
176185

177186
for (var value of range(0, 3)) {
178-
console.log(value);
187+
console.log(value); // 0, 1, 2
179188
}
180189
```
181190

182-
上面代码是一个类部署Iterator接口的写法`Symbol.iterator`属性对应一个函数,执行后返回当前对象的遍历器对象。
191+
上面代码是一个类部署 Iterator 接口的写法`Symbol.iterator`属性对应一个函数,执行后返回当前对象的遍历器对象。
183192

184193
下面是通过遍历器实现指针结构的例子。
185194

@@ -190,24 +199,17 @@ function Obj(value) {
190199
}
191200

192201
Obj.prototype[Symbol.iterator] = function() {
193-
var iterator = {
194-
next: next
195-
};
202+
var iterator = { next: next };
196203

197204
var current = this;
198205

199206
function next() {
200207
if (current) {
201208
var value = current.value;
202209
current = current.next;
203-
return {
204-
done: false,
205-
value: value
206-
};
210+
return { done: false, value: value };
207211
} else {
208-
return {
209-
done: true
210-
};
212+
return { done: true };
211213
}
212214
}
213215
return iterator;
@@ -221,16 +223,13 @@ one.next = two;
221223
two.next = three;
222224

223225
for (var i of one){
224-
console.log(i);
226+
console.log(i); // 1, 2, 3
225227
}
226-
// 1
227-
// 2
228-
// 3
229228
```
230229

231230
上面代码首先在构造函数的原型链上部署`Symbol.iterator`方法,调用该方法会返回遍历器对象`iterator`,调用该对象的`next`方法,在返回一个值的同时,自动将内部指针移到下一个实例。
232231

233-
下面是另一个为对象添加Iterator接口的例子
232+
下面是另一个为对象添加 Iterator 接口的例子
234233

235234
```javascript
236235
let obj = {
@@ -254,7 +253,7 @@ let obj = {
254253
};
255254
```
256255

257-
对于类似数组的对象(存在数值键名和length属性),部署Iterator接口,有一个简便方法,就是`Symbol.iterator`方法直接引用数组的Iterator接口
256+
对于类似数组的对象(存在数值键名和`length`属性),部署 Iterator 接口,有一个简便方法,就是`Symbol.iterator`方法直接引用数组的 Iterator 接口
258257

259258
```javascript
260259
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
@@ -304,7 +303,7 @@ obj[Symbol.iterator] = () => 1;
304303
[...obj] // TypeError: [] is not a function
305304
```
306305

307-
上面代码中,变量obj的Symbol.iterator方法对应的不是遍历器生成函数,因此报错。
306+
上面代码中,变量`obj``Symbol.iterator`方法对应的不是遍历器生成函数,因此报错。
308307

309308
有了遍历器接口,数据结构就可以用`for...of`循环遍历(详见下文),也可以使用`while`循环遍历。
310309

@@ -320,13 +319,13 @@ while (!$result.done) {
320319

321320
上面代码中,`ITERABLE`代表某种可遍历的数据结构,`$iterator`是它的遍历器对象。遍历器对象每次移动指针(`next`方法),都检查一下返回值的`done`属性,如果遍历还没结束,就移动遍历器对象的指针到下一步(`next`方法),不断循环。
322321

323-
## 调用Iterator接口的场合
322+
## 调用 Iterator 接口的场合
324323

325-
有一些场合会默认调用Iterator接口(即`Symbol.iterator`方法),除了下文会介绍的`for...of`循环,还有几个别的场合。
324+
有一些场合会默认调用 Iterator 接口(即`Symbol.iterator`方法),除了下文会介绍的`for...of`循环,还有几个别的场合。
326325

327326
**(1)解构赋值**
328327

329-
对数组和Set结构进行解构赋值时,会默认调用`Symbol.iterator`方法。
328+
对数组和 Set 结构进行解构赋值时,会默认调用`Symbol.iterator`方法。
330329

331330
```javascript
332331
let set = new Set().add('a').add('b').add('c');
@@ -340,7 +339,7 @@ let [first, ...rest] = set;
340339

341340
**(2)扩展运算符**
342341

343-
扩展运算符(...)也会调用默认的iterator接口
342+
扩展运算符(...)也会调用默认的 Iterator 接口
344343

345344
```javascript
346345
// 例一
@@ -353,17 +352,17 @@ let arr = ['b', 'c'];
353352
// ['a', 'b', 'c', 'd']
354353
```
355354

356-
上面代码的扩展运算符内部就调用Iterator接口
355+
上面代码的扩展运算符内部就调用 Iterator 接口
357356

358-
实际上,这提供了一种简便机制,可以将任何部署了Iterator接口的数据结构,转为数组。也就是说,只要某个数据结构部署了Iterator接口,就可以对它使用扩展运算符,将其转为数组。
357+
实际上,这提供了一种简便机制,可以将任何部署了 Iterator 接口的数据结构,转为数组。也就是说,只要某个数据结构部署了 Iterator 接口,就可以对它使用扩展运算符,将其转为数组。
359358

360359
```javascript
361360
let arr = [...iterable];
362361
```
363362

364363
**(3)yield* **
365364

366-
yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
365+
`yield*`后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
367366

368367
```javascript
369368
let generator = function* () {
@@ -392,9 +391,9 @@ iterator.next() // { value: undefined, done: true }
392391
- Promise.all()
393392
- Promise.race()
394393

395-
## 字符串的Iterator接口
394+
## 字符串的 Iterator 接口
396395

397-
字符串是一个类似数组的对象,也原生具有Iterator接口
396+
字符串是一个类似数组的对象,也原生具有 Iterator 接口
398397

399398
```javascript
400399
var someString = "hi";

docs/reference.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
- kangax, [Javascript quiz. ES6 edition](http://perfectionkills.com/javascript-quiz-es6/): ES6小测试
3838
- Jeremy Fairbank, [HTML5DevConf ES7 and Beyond!](https://speakerdeck.com/jfairbank/html5devconf-es7-and-beyond): ES7新增语法点介绍
3939

40-
## let和const
40+
## let 和 const
4141

4242
- Kyle Simpson, [For and against let](http://davidwalsh.name/for-and-against-let): 讨论let命令的作用域
4343
- kangax, [Why typeof is no longer “safe”](http://es-discourse.com/t/why-typeof-is-no-longer-safe/15): 讨论在块级作用域内,let命令的变量声明和赋值的行为
@@ -65,6 +65,7 @@
6565
- Mathias Bynens, [Unicode-aware regular expressions in ES6](https://mathiasbynens.be/notes/es6-unicode-regex): 详细介绍正则表达式的u修饰符
6666
- Axel Rauschmayer, [New regular expression features in ECMAScript 6](http://www.2ality.com/2015/07/regexp-es6.html):ES6正则特性的详细介绍
6767
- Yang Guo, [RegExp lookbehind assertions](http://v8project.blogspot.jp/2016/02/regexp-lookbehind-assertions.html):介绍后行断言
68+
- Axel Rauschmayer, [ES proposal: RegExp named capture groups](http://2ality.com/2017/05/regexp-named-capture-groups.html): 具名组匹配的介绍
6869

6970
## 数值
7071

0 commit comments

Comments
 (0)