Skip to content

Commit 78b4c2f

Browse files
committed
修改string/模板字符串
1 parent ed562a4 commit 78b4c2f

File tree

6 files changed

+284
-21
lines changed

6 files changed

+284
-21
lines changed

docs/class.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,24 @@ import { lastName as surname } from './profile';
153153

154154
```
155155

156+
ES6支持多重加载,即所加载的模块中又加载其他模块。
157+
158+
```javascript
159+
160+
import { Vehicle } from './Vehicle';
161+
162+
class Car extends Vehicle {
163+
move () {
164+
console.log(this.name + ' is spinning wheels...')
165+
}
166+
}
167+
168+
export { Car }
169+
170+
```
171+
172+
上面的模块先加载Vehicle模块,然后在其基础上添加了move方法,再作为一个新模块输出。
173+
156174
**(2)模块的整体输入,module命令**
157175

158176
export命令除了输出变量,还可以输出方法或类(class)。下面是一个circle.js文件,它输出两个方法area和circumference。

docs/generator.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ hw.next()
5252

5353
总结一下,Generator函数使用iterator接口,每次调用next方法的返回值,就是一个标准的iterator返回值:有着value和done两个属性的对象。其中,value是yield语句后面那个表达式的值,done是一个布尔值,表示是否遍历结束。
5454

55+
由于Generator函数本身就能生成遍历器,所以它的Symbol.iterator属性指向自身。
56+
57+
```javascript
58+
59+
function* gen(){
60+
// some code
61+
}
62+
63+
gen[Symbol.iterator]() === gen
64+
// true
65+
66+
```
67+
68+
上面代码中,gen是一个Generator函数,它的Symbol.iterator属性就指向它自己。
69+
5570
由于Generator函数返回的遍历器,只有调用next方法才会遍历下一个成员,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志,next方法遇到yield,就会暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回对象的value属性的值。当下一次调用next方法时,再继续往下执行,直到遇到下一个yield语句。如果没有再遇到新的yield语句,就一直运行到函数结束,将return语句后面的表达式的值,作为value属性的值,如果该函数没有return语句,则value属性的值为undefined。另一方面,由于yield后面的表达式,直到调用next方法时才会执行,因此等于为JavaScript提供了手动的“惰性求值”(Lazy Evaluation)的语法功能。
5671

5772
yield语句与return语句有点像,都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield语句。正常函数只能返回一个值,因为只能执行一次return;Generator函数可以返回一系列的值,因为可以有任意多个yield。从另一个角度看,也可以说Generator生成了一系列的值,这也就是它的名称的来历(在英语中,generator这个词是“生成器”的意思)。

docs/iterator.md

Lines changed: 81 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Iterator(遍历器)
44

5+
### 语法
6+
57
遍历器(Iterator)是一种接口规格,任何对象只要部署这个接口,就可以完成遍历操作。它的作用有两个,一是为各种数据结构,提供一个统一的、简便的接口,二是使得对象的属性能够按某种次序排列。在ES6中,遍历操作特指for...of循环,即Iterator接口主要供for...of循环使用。
68

79
遍历器提供了一个指针,指向当前对象的某个属性,使用next方法,就可以将指针移动到下一个属性。next方法返回一个包含value和done两个属性的对象。其中,value属性是当前遍历位置的值,done属性是一个布尔值,表示遍历是否结束。下面是一个模拟next方法返回值的例子。
@@ -51,9 +53,15 @@ it.next().value // '2'
5153

5254
```
5355

54-
上面的例子,只是为了说明next方法返回值的结构。Iterator接口返回的遍历器,原生具备next方法,不用自己部署。所以,真正需要部署的是Iterator接口,让其返回一个遍历器。在ES6中,有三类数据结构原生具备Iterator接口:数组、类似数组的对象、Set和Map结构。除此之外,其他数据结构(主要是对象)的Iterator接口都需要自己部署。
56+
上面的例子,说明了next方法返回值的结构:value和done两个属性。
57+
58+
### Iterator接口的部署
59+
60+
具有Iterator接口的对象,都能被for...of循环遍历(见后文的介绍)。所谓Iterator接口,就是指它会返回一个遍历器对象,该对象具备next方法,每次调用该方法,会依次返回一个具有上节提到的value和done两个属性的新对象,指向原对象的一个成员。
61+
62+
在ES6中,有三类数据结构原生具备Iterator接口:数组、类似数组的对象、Set和Map结构。除此之外,其他数据结构(主要是对象)的Iterator接口都需要自己部署。其他对象需要手动部署Iterator接口,让其返回一个遍历器。
5563

56-
下面就是如何部署Iterator接口。一个对象如果要有Iterator接口,必须部署一个@@iterator方法(原型链上的对象具有该方法也可),该方法部署在一个键名为`Symbol.iterator`的属性上,对应的键值是一个函数,该函数返回一个遍历器对象。
64+
一个对象如果要有Iterator接口,必须部署一个@@iterator方法(原型链上的对象具有该方法也可),该方法部署在一个键名为`Symbol.iterator`的属性上,对应的键值是一个函数,该函数返回一个遍历器对象。
5765

5866
```javascript
5967

@@ -69,7 +77,59 @@ class MySpecialTree {
6977

7078
上面代码是一个类部署Iterator接口的写法。`Symbol.iterator`是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为Symbol的特殊值,所以要放在方括号内(请参考Symbol一节)。这里要注意,@@iterator的键名是`Symbol.iterator`,键值是一个方法(函数),该方法执行后,返回一个当前对象的遍历器。
7179

72-
下面是为对象添加Iterator接口的例子。
80+
下面是一个例子。
81+
82+
```javascript
83+
84+
function O(value){
85+
this.value = value;
86+
this.next = null;
87+
}
88+
89+
O.prototype[Symbol.iterator] = function(){
90+
91+
var iterator = {
92+
next: next
93+
};
94+
95+
var current = this;
96+
97+
function next(){
98+
if (current){
99+
var value = current.value;
100+
var done = current == null;
101+
current = current.next;
102+
return {
103+
done: done,
104+
value: value
105+
}
106+
} else {
107+
return {
108+
done: true
109+
}
110+
}
111+
}
112+
return iterator;
113+
}
114+
115+
var one = new O(1);
116+
var two = new O(2);
117+
var three = new O(3);
118+
one.next = two;
119+
two.next = three;
120+
121+
for (var i of one){
122+
console.log(i)
123+
}
124+
// 1
125+
// 2
126+
// 3
127+
128+
```
129+
130+
上面代码首先在构造函数的原型链上部署Symbol.iterator方法,调用该方法会返回遍历器对象iterator,调用该对象的next方法,在返回一个值的同时,自动将内部指针移到下一个实例。
131+
132+
下面是另一个为对象添加Iterator接口的例子。
73133

74134
```javascript
75135

@@ -95,6 +155,22 @@ let obj = {
95155

96156
```
97157

158+
如果`Symbol.iterator`方法返回的不是遍历器,解释引擎将会报错。
159+
160+
```javascript
161+
162+
var obj = {};
163+
164+
obj[Symbol.iterator] = () => 1;
165+
166+
[...obj] // TypeError: [] is not a function
167+
168+
```
169+
170+
上面代码中,变量obj的@@iterator方法返回的不是遍历器,因此报错。
171+
172+
### 原生具备iterator接口的数据结构
173+
98174
《数组的扩展》一章中提到,ES6对数组提供entries()、keys()和values()三个方法,就是返回三个遍历器。
99175

100176
```javascript
@@ -159,6 +235,8 @@ str // "hi"
159235

160236
上面代码中,字符串str的`Symbol.iterator`方法被修改了,所以扩展运算符(...)返回的值变成了bye,而字符串本身还是hi。
161237

238+
### Iterator接口与Generator函数
239+
162240
部署`Symbol.iterator`方法的最简单实现,还是使用下一节要提到的Generator函数。
163241

164242
```javascript
@@ -189,20 +267,6 @@ for (let x of obj) {
189267

190268
```
191269

192-
如果`Symbol.iterator`方法返回的不是遍历器,解释引擎将会报错。
193-
194-
```javascript
195-
196-
var obj = {};
197-
198-
obj[Symbol.iterator] = () => 1;
199-
200-
[...obj] // TypeError: [] is not a function
201-
202-
```
203-
204-
上面代码中,变量obj的@@iterator方法返回的不是遍历器,因此报错。
205-
206270
## for...of循环
207271

208272
ES6中,一个对象只要部署了@@iterator方法,就被视为具有iterator接口,就可以用for...of循环遍历它的值。也就是说,for...of循环内部调用是原对象的`Symbol.iterator`方法。

docs/reference.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
- Luke Hoban, [ES6 features](https://github.com/lukehoban/es6features)
2020
- Traceur-compiler, [Language Features](https://github.com/google/traceur-compiler/wiki/LanguageFeatures): Traceur文档列出的一些ES6例子
2121
- Axel Rauschmayer, [ECMAScript 6: what’s next for JavaScript?](https://speakerdeck.com/rauschma/ecmascript-6-whats-next-for-javascript-august-2014): 关于ES6新增语法的综合介绍,有很多例子
22+
- Toby Ho, [ES6 in io.js](http://davidwalsh.name/es6-io)
23+
2224

2325
## 语法点
2426

@@ -31,7 +33,12 @@
3133
- Dmitry Soshnikov, [ES6 Notes: Default values of parameters](http://dmitrysoshnikov.com/ecmascript/es6-notes-default-values-of-parameters/): 介绍参数的默认值
3234
- Mozilla Developer Network, [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet):介绍WeakSet数据结构
3335
- Axel Rauschmayer, [ECMAScript 6: maps and sets](http://www.2ality.com/2015/01/es6-maps-sets.html): Set和Map结构的详细介绍
36+
37+
## 字符串
38+
3439
- Mathias Bynens, [Unicode-aware regular expressions in ES6](https://mathiasbynens.be/notes/es6-unicode-regex): 详细介绍正则表达式的u修饰符
40+
- Nicholas C. Zakas, [A critical review of ECMAScript 6 quasi-literals](http://www.nczonline.net/blog/2012/08/01/a-critical-review-of-ecmascript-6-quasi-literals/)
41+
- Mozilla Developer Network, [Template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings)
3542

3643
## Object
3744

docs/set-map.md

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,16 @@ WeakSet结构与Set类似,也是不重复的值的集合。但是,它与Set
256256

257257
首先,WeakSet的成员只能是对象,而不能是其他类型的值。其次,WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet之中。这个特点意味着,无法引用WeakSet的成员,因此WeakSet是不可遍历的。
258258

259+
```javascript
260+
261+
var ws = new WeakSet();
262+
ws.add(1)
263+
// TypeError: Invalid value used in weak set
264+
265+
```
266+
267+
上面代码试图向WeakSet添加一个数值,结果报错。
268+
259269
WeakSet是一个构造函数,可以使用new命令,创建WeakSet数据结构。
260270

261271
```javascript
@@ -303,6 +313,25 @@ ws.clear();
303313

304314
```
305315

316+
WeakSet没有size属性,没有办法遍历它的成员。
317+
318+
```javascript
319+
320+
ws.size
321+
// undefined
322+
323+
ws.forEach(function(item){ console.log('WeakSet has ' + item)})
324+
// TypeError: undefined is not a function
325+
326+
ws.forEach
327+
// undefined
328+
329+
```
330+
331+
上面代码试图获取size和forEach属性,结果都不能成功。
332+
333+
WeakSet不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保存成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
334+
306335
## Map
307336

308337
**(1)基本用法**
@@ -611,24 +640,36 @@ WeakMap的设计目的在于,键名是对象的弱引用(垃圾回收机制
611640
612641
```javascript
613642

614-
var map = new WeakMap();
643+
var wm = new WeakMap();
615644
var element = document.querySelector(".element");
616645

617-
map.set(element, "Original");
646+
wm.set(element, "Original");
618647

619-
var value = map.get(element);
648+
var value = wm.get(element);
620649
console.log(value); // "Original"
621650

622651
element.parentNode.removeChild(element);
623652
element = null;
624653

625-
value = map.get(element);
654+
value = wm.get(element);
626655
console.log(value); // undefined
627656

628657
```
629658
630659
WeakMap与Map在API上的区别主要是两个,一是没有遍历操作(即没有key()、values()和entries()方法),也没有size属性;二是无法清空,即不支持clear方法。这与WeakMap的键不被计入引用、被垃圾回收机制忽略有关。因此,WeakMap只有四个方法可用:get()、set()、has()、delete()。
631660
661+
```javascript
662+
663+
var wm = new WeakMap();
664+
665+
wm.size
666+
// undefined
667+
668+
wm.forEach
669+
// undefined
670+
671+
```
672+
632673
WeakMap的一个用处是部署私有属性。
633674
634675
```javascript

0 commit comments

Comments
 (0)