Skip to content

Commit e9f7c51

Browse files
committed
edit array, set-map
1 parent bf75bab commit e9f7c51

File tree

3 files changed

+68
-37
lines changed

3 files changed

+68
-37
lines changed

docs/array.md

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
`Array.from`方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。
66

7+
下面是一个类似数组的对象,`Array.from`将它转为真正的数组。
8+
79
```javascript
810
let arrayLike = {
911
'0': 'a',
@@ -19,34 +21,41 @@ var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
1921
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
2022
```
2123

22-
下面是更多的例子
24+
实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的`arguments`对象。`Array.from`都可以将它们转为真正的数组
2325

2426
```javascript
25-
Array.from('hello')
26-
// ['h', 'e', 'l', 'l', 'o']
27-
28-
Array.from([1, 2, 3])
29-
// [1, 2, 3]
30-
31-
let namesSet = new Set(['a', 'b'])
32-
Array.from(namesSet) // ['a', 'b']
33-
27+
// NodeList对象
3428
let ps = document.querySelectorAll('p');
3529
Array.from(ps).forEach(function (p) {
3630
console.log(p);
3731
});
32+
33+
// arguments对象
34+
function foo() {
35+
var args = Array.from(arguments);
36+
// ...
37+
}
3838
```
3939

40-
上面代码中,`querySelectorAll`方法返回的是一个类似数组的对象,只有将这个对象转为真正的数组,才能使用forEach方法
40+
上面代码中,`querySelectorAll`方法返回的是一个类似数组的对象,只有将这个对象转为真正的数组,才能使用`forEach`方法
4141

42-
`Array.from`方法可以将函数的`arguments`对象,转为数组
42+
只要是部署了Iterator接口的数据结构,`Array.from`都能将其转为数组
4343

4444
```javascript
45-
function foo() {
46-
var args = Array.from(arguments);
47-
}
45+
Array.from('hello')
46+
// ['h', 'e', 'l', 'l', 'o']
4847

49-
foo('a', 'b', 'c');
48+
let namesSet = new Set(['a', 'b'])
49+
Array.from(namesSet) // ['a', 'b']
50+
```
51+
52+
上面代码中,字符串和Set结构都具有Iterator接口,因此可以被`Array.from`转为真正的数组。
53+
54+
如果参数是一个真正的数组,`Array.from`会返回一个一模一样的新数组。
55+
56+
```javascript
57+
Array.from([1, 2, 3])
58+
// [1, 2, 3]
5059
```
5160

5261
值得提醒的是,扩展运算符(`...`)也可以将某些数据结构转为数组。
@@ -61,16 +70,14 @@ function foo() {
6170
[...document.querySelectorAll('div')]
6271
```
6372

64-
扩展运算符背后调用的是遍历器接口(`Symbol.iterator`),如果一个对象没有部署这个接口,就无法转换。`Array.from`方法就不存在这个问题,比如下面的这个例子,扩展运算符就无法转换。
65-
66-
所谓类似数组的对象,本质特征只有一点,即必须有`length`属性。因此,任何有`length`属性的对象,都可以通过`Array.from`方法转为数组。
73+
扩展运算符背后调用的是遍历器接口(`Symbol.iterator`),如果一个对象没有部署这个接口,就无法转换。`Array.from`方法则是还支持类似数组的对象。所谓类似数组的对象,本质特征只有一点,即必须有`length`属性。因此,任何有`length`属性的对象,都可以通过`Array.from`方法转为数组,而此时扩展运算符就无法转换。
6774

6875
```javascript
6976
Array.from({ length: 3 });
7077
// [ undefined, undefined, undefinded ]
7178
```
7279

73-
上面代码中,`Array.from`返回了一个具有三个成员的数组,每个位置的值都是`undefined`
80+
上面代码中,`Array.from`返回了一个具有三个成员的数组,每个位置的值都是`undefined`扩展运算符转换不了这个对象。
7481

7582
对于还没有部署该方法的浏览器,可以用`Array.prototype.slice`方法替代。
7683

@@ -80,7 +87,7 @@ const toArray = (() =>
8087
)();
8188
```
8289

83-
`Array.from`还可以接受第二个参数,作用类似于数组的`map`方法,用来对每个元素进行处理。
90+
`Array.from`还可以接受第二个参数,作用类似于数组的`map`方法,用来对每个元素进行处理,将处理后的值放入返回的数组
8491

8592
```JavaScript
8693
Array.from(arrayLike, x => x * x);
@@ -91,6 +98,18 @@ Array.from([1, 2, 3], (x) => x * x)
9198
// [1, 4, 9]
9299
```
93100

101+
下面的例子是取出一组DOM节点的文本内容。
102+
103+
```javascript
104+
let spans = document.querySelectorAll('span.name');
105+
106+
// map()
107+
let names1 = Array.prototype.map.call(spans, s => s.textContent);
108+
109+
// Array.from()
110+
let names2 = Array.from(spans, s => s.textContent)
111+
```
112+
94113
下面的例子将数组中布尔值为`false`的成员转为`0`
95114

96115
```javascript
@@ -110,7 +129,7 @@ typesOf(null, [], NaN)
110129

111130
如果`map`函数里面用到了`this`关键字,还可以传入`Array.from`的第三个参数,用来绑定`this`
112131

113-
`Array.from()`可以将各种值转为真正的数组,并且还提供`map`功能。这实际上意味着,你可以在数组里造出任何想要的值
132+
`Array.from()`可以将各种值转为真正的数组,并且还提供`map`功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法
114133

115134
```javascript
116135
Array.from({ length: 2 }, () => 'jack')
@@ -240,9 +259,9 @@ i32a.copyWithin(0, 2);
240259
}) // 2
241260
```
242261

243-
这两个方法都可以接受第二个参数,用来绑定回调函数的this对象
262+
这两个方法都可以接受第二个参数,用来绑定回调函数的`this`对象
244263

245-
另外,这两个方法都可以发现NaN,弥补了数组的IndexOf方法的不足
264+
另外,这两个方法都可以发现`NaN`,弥补了数组的`IndexOf`方法的不足
246265

247266
```javascript
248267
[NaN].indexOf(NaN)
@@ -252,7 +271,7 @@ i32a.copyWithin(0, 2);
252271
// 0
253272
```
254273

255-
上面代码中,`indexOf`方法无法识别数组的NaN成员,但是`findIndex`方法可以借助`Object.is`方法做到。
274+
上面代码中,`indexOf`方法无法识别数组的`NaN`成员,但是`findIndex`方法可以借助`Object.is`方法做到。
256275

257276
## 数组实例的fill()
258277

@@ -275,6 +294,8 @@ new Array(3).fill(7)
275294
// ['a', 7, 'c']
276295
```
277296

297+
上面代码表示,`fill`方法从1号位开始,向原数组填充7,到2号位之前结束。
298+
278299
## 数组实例的entries(),keys()和values()
279300

280301
ES6提供三个新的方法——`entries()``keys()``values()`——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用`for...of`循环进行遍历,唯一的区别是`keys()`是对键名的遍历、`values()`是对键值的遍历,`entries()`是对键值对的遍历。

docs/module.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ console.log(counter); // 4
438438

439439
上面代码说明,ES6模块输入的变量`counter`是活的,完全反映其所在模块`lib.js`内部的变化。
440440

441-
还是举本章开头时的例子
441+
再举一个出现在`export`一节中的例子
442442

443443
```javascript
444444
// m1.js

docs/set-map.md

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -212,17 +212,23 @@ set = new Set([...set].filter(x => (x % 2) == 0));
212212
// 返回Set结构:{2, 4}
213213
```
214214

215-
因此使用Set,可以很容易地实现并集(Union)和交集(Intersect)。
215+
因此使用Set,可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)。
216216

217217
```javascript
218218
let a = new Set([1, 2, 3]);
219219
let b = new Set([4, 3, 2]);
220220

221+
// 并集
221222
let union = new Set([...a, ...b]);
222223
// [1, 2, 3, 4]
223224

225+
// 交集
224226
let intersect = new Set([...a].filter(x => b.has(x)));
225227
// [2, 3]
228+
229+
// 差集
230+
let difference = new Set([...a].filter(x => !b.has(x)));
231+
// [1]
226232
```
227233

228234
Set结构的实例的forEach方法,用于对每个成员执行某种操作,没有返回值。
@@ -321,7 +327,7 @@ ws.forEach(function(item){ console.log('WeakSet has ' + item)})
321327

322328
上面代码试图获取size和forEach属性,结果都不能成功。
323329

324-
WeakSet不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保存成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
330+
WeakSet不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
325331

326332
下面是WeakMap的另一个例子。
327333

@@ -385,7 +391,7 @@ map.has("title") // true
385391
map.get("title") // "Author"
386392
```
387393

388-
上面代码在新建Map实例时,就指定了两个键name和title
394+
上面代码在新建Map实例时,就指定了两个键`name``title`
389395

390396
Map构造函数接受数组作为参数,实际上执行的是下面的算法。
391397

@@ -402,14 +408,17 @@ items.forEach(([key, value]) => map.set(key, value));
402408

403409
```javascript
404410
let map = new Map();
405-
map.set(1, 'aaa');
406-
map.set(1, 'bbb');
411+
412+
map
413+
.set(1, 'aaa')
414+
.set(1, 'bbb');
415+
407416
map.get(1) // "bbb"
408417
```
409418

410-
上面代码对键1连续赋值两次,后一次的值覆盖前一次的值。
419+
上面代码对键`1`连续赋值两次,后一次的值覆盖前一次的值。
411420

412-
如果读取一个未知的键,则返回undefined
421+
如果读取一个未知的键,则返回`undefined`
413422

414423
```javascript
415424
new Map().get('asfddfsasadf')
@@ -425,7 +434,7 @@ map.set(['a'], 555);
425434
map.get(['a']) // undefined
426435
```
427436

428-
上面代码的set和get方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get方法无法读取该键,返回undefined
437+
上面代码的`set``get`方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此`get`方法无法读取该键,返回`undefined`
429438

430439
同理,同样的值的两个实例,在Map结构中被视为两个键。
431440

@@ -435,14 +444,15 @@ var map = new Map();
435444
var k1 = ['a'];
436445
var k2 = ['a'];
437446

438-
map.set(k1, 111);
439-
map.set(k2, 222);
447+
map
448+
.set(k1, 111)
449+
.set(k2, 222);
440450

441451
map.get(k1) // 111
442452
map.get(k2) // 222
443453
```
444454

445-
上面代码中,变量k1和k2的值是一样的,但是它们在Map结构中被视为两个键。
455+
上面代码中,变量`k1``k2`的值是一样的,但是它们在Map结构中被视为两个键。
446456

447457
由上可知,Map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。
448458

0 commit comments

Comments
 (0)