Skip to content

Commit 7c51ca6

Browse files
committed
edit string & function
1 parent 1a9d77f commit 7c51ca6

File tree

2 files changed

+111
-39
lines changed

2 files changed

+111
-39
lines changed

docs/function.md

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ function f(a, ...b, c) {
259259

260260
## 扩展运算符
261261

262+
### 含义
263+
262264
扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。
263265

264266
```javascript
@@ -297,6 +299,8 @@ var args = [0, 1];
297299
f(-1, ...args, 2, ...[3]);
298300
```
299301

302+
### 替代数组的apply方法
303+
300304
由于扩展运算符可以展开数组,所以不再需要`apply`方法,将数组转为函数的参数了。
301305

302306
```javascript
@@ -342,33 +346,27 @@ arr1.push(...arr2);
342346

343347
上面代码的ES5写法中,`push`方法的参数不能是数组,所以只好通过`apply`方法变通使用`push`方法。有了扩展运算符,就可以直接将数组传入`push`方法。
344348

345-
扩展运算符可以简化很多种ES5的写法
349+
下面是另外一个例子
346350

347351
```javascript
348-
// ES5
349-
[1, 2].concat(more)
350-
// ES6
351-
[1, 2, ...more]
352-
353-
// ES5
354-
list.push.apply(list, [3, 4])
355-
// ES6
356-
list.push(...[3, 4])
357-
358-
// ES5
359-
a = list[0], rest = list.slice(1)
360-
// ES6
361-
[a, ...rest] = list
362-
363352
// ES5
364353
new (Date.bind.apply(Date, [null, 2015, 1, 1]))
365354
// ES6
366355
new Date(...[2015, 1, 1]);
367356
```
368357

369-
上面的第一个例子,其实提供了数组合并的新写法。
358+
### 扩展运算符的应用
359+
360+
**(1)合并数组**
361+
362+
扩展运算符提供了数组合并的新写法。
370363

371364
```javascript
365+
// ES5
366+
[1, 2].concat(more)
367+
// ES6
368+
[1, 2, ...more]
369+
372370
var arr1 = ['a', 'b'];
373371
var arr2 = ['c'];
374372
var arr3 = ['d', 'e'];
@@ -382,7 +380,18 @@ arr1.concat(arr2, arr3));
382380
// [ 'a', 'b', 'c', 'd', 'e' ]
383381
```
384382

385-
扩展运算符也可以与解构赋值结合起来,用于生成数组。
383+
**(2)与解构赋值结合**
384+
385+
扩展运算符可以与解构赋值结合起来,用于生成数组。
386+
387+
```javascript
388+
// ES5
389+
a = list[0], rest = list.slice(1)
390+
// ES6
391+
[a, ...rest] = list
392+
```
393+
394+
下面是另外一些例子。
386395

387396
```javascript
388397
const [first, ...rest] = [1, 2, 3, 4, 5];
@@ -408,14 +417,18 @@ const [first, ...middle, last] = [1, 2, 3, 4, 5];
408417
// 报错
409418
```
410419

420+
**(3)函数的返回值**
421+
411422
JavaScript的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。
412423

413424
```javascript
414425
var dateFields = readDateFields(database);
415426
var d = new Date(...dateFields);
416427
```
417428

418-
上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数Date。
429+
上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数`Date`
430+
431+
**(4)字符串**
419432

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

@@ -424,6 +437,39 @@ var d = new Date(...dateFields);
424437
// [ "h", "e", "l", "l", "o" ]
425438
```
426439

440+
上面的写法,有一个重要的好处,那就是能够正确识别32位的Unicode字符。
441+
442+
```javascript
443+
'x\uD83D\uDE80y'.length // 4
444+
[...'x\uD83D\uDE80y'].length // 3
445+
```
446+
447+
上面代码的第一种写法,JavaScript会将32位Unicode字符,识别为2个字符,采用扩展运算符就没有这个问题。因此,正确返回字符串长度的函数,可以像下面这样写。
448+
449+
```javascript
450+
function length(str) {
451+
return [...str].length;
452+
}
453+
454+
length('x\uD83D\uDE80y') // 3
455+
```
456+
457+
凡是涉及到操作32位Unicode字符的函数,都有这个问题。因此,最好都用扩展运算符改写。
458+
459+
```javascript
460+
let str = 'x\uD83D\uDE80y';
461+
462+
str.split('').reverse().join('')
463+
// 'y\uDE80\uD83Dx'
464+
465+
[...str].reverse().join('')
466+
// 'y\uD83D\uDE80x'
467+
```
468+
469+
上面代码中,如果不用扩展运算符,字符串的`reverse`操作就不正确。
470+
471+
**(5)类似数组的对象**
472+
427473
任何类似数组的对象,都可以用扩展运算符转为真正的数组。
428474

429475
```javascript
@@ -433,6 +479,8 @@ var array = [...nodeList];
433479

434480
上面代码中,`querySelectorAll`方法返回的是一个`nodeList`对象,扩展运算符可以将其转为真正的数组。
435481

482+
**(6)Map和Set结构,Generator函数**
483+
436484
扩展运算符内部调用的是数据结构的Iterator接口,因此只要具有Iterator接口的对象,都可以使用扩展运算符,比如Map结构。
437485

438486
```javascript

docs/string.md

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,24 +65,44 @@ s.charCodeAt(0) // 55362
6565
s.charCodeAt(1) // 57271
6666
```
6767

68-
上面代码中,汉字“𠮷”的码点是0x20BB7,UTF-16编码为0xD842 0xDFB7(十进制为55362 57271),需要4个字节储存。对于这种4个字节的字符,JavaScript不能正确处理,字符串长度会误判为2,而且charAt方法无法读取字符,charCodeAt方法只能分别返回前两个字节和后两个字节的值
68+
上面代码中,汉字“𠮷”的码点是`0x20BB7`,UTF-16编码为`0xD842 0xDFB7`(十进制为55362 57271),需要4个字节储存。对于这种4个字节的字符,JavaScript不能正确处理,字符串长度会误判为2,而且`charAt`方法无法读取整个字符,`charCodeAt`方法只能分别返回前两个字节和后两个字节的值
6969

70-
ES6提供了codePointAt方法,能够正确处理4个字节储存的字符,返回一个字符的码点。
70+
ES6提供了`codePointAt`方法,能够正确处理4个字节储存的字符,返回一个字符的码点。
7171

7272
```javascript
73-
var s = "𠮷a";
73+
var s = '𠮷a';
7474

7575
s.codePointAt(0) // 134071
7676
s.codePointAt(1) // 57271
7777

7878
s.charCodeAt(2) // 97
7979
```
8080

81-
codePointAt方法的参数,是字符在字符串中的位置(从0开始)。上面代码中,JavaScript将“𠮷a”视为三个字符,codePointAt方法在第一个字符上,正确地识别了“𠮷”,返回了它的十进制码点134071(即十六进制的20BB7)。在第二个字符(即“𠮷”的后两个字节)和第三个字符“a”上,codePointAt方法的结果与charCodeAt方法相同
81+
`codePointAt`方法的参数,是字符在字符串中的位置(从0开始)。上面代码中,JavaScript将“𠮷a”视为三个字符,codePointAt方法在第一个字符上,正确地识别了“𠮷”,返回了它的十进制码点134071(即十六进制的`20BB7`)。在第二个字符(即“𠮷”的后两个字节)和第三个字符“a”上,`codePointAt`方法的结果与`charCodeAt`方法相同
8282

83-
总之,codePointAt方法会正确返回四字节的UTF-16字符的码点。对于那些两个字节储存的常规字符,它的返回结果与charCodeAt方法相同
83+
总之,`codePointAt`方法会正确返回32位的UTF-16字符的码点。对于那些两个字节储存的常规字符,它的返回结果与`charCodeAt`方法相同
8484

85-
codePointAt方法是测试一个字符由两个字节还是由四个字节组成的最简单方法。
85+
`codePointAt`方法返回的是码点的十进制值,如果想要十六进制的值,可以使用`toString`方法转换一下。
86+
87+
```javascript
88+
var s = '𠮷a';
89+
90+
s.codePointAt(0).toString(16) // "20bb7"
91+
s.charCodeAt(2).toString(16) // "61"
92+
```
93+
94+
你可能注意到了,`codePointAt`方法的参数,仍然是不正确的。比如,上面代码中,字符`a`在字符串`s`的正确位置序号应该是1,但是必须向`charCodeAt`方法传入2。解决这个问题的一个办法是使用`for...of`循环,因为它会正确识别32位的UTF-16字符。
95+
96+
```javascript
97+
var s = '𠮷a';
98+
for (let ch of s) {
99+
console.log(ch.codePointAt(0).toString(16));
100+
}
101+
// "20bb7"
102+
// ""
103+
```
104+
105+
`codePointAt`方法是测试一个字符由两个字节还是由四个字节组成的最简单方法。
86106

87107
```javascript
88108
function is32Bit(c) {
@@ -95,7 +115,7 @@ is32Bit("a") // false
95115

96116
## String.fromCodePoint()
97117

98-
ES5提供`String.fromCharCode`方法,用于从码点返回对应字符,但是这个方法不能识别辅助平面的字符(编号大于`0xFFFF`)。
118+
ES5提供`String.fromCharCode`方法,用于从码点返回对应字符,但是这个方法不能识别32位的UTF-16字符(Unicode编号大于`0xFFFF`)。
99119

100120
```javascript
101121
String.fromCharCode(0x20BB7)
@@ -109,9 +129,13 @@ ES6提供了`String.fromCodePoint`方法,可以识别`0xFFFF`的字符,弥
109129
```javascript
110130
String.fromCodePoint(0x20BB7)
111131
// "𠮷"
132+
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
133+
// true
112134
```
113135

114-
注意,`fromCodePoint`方法定义在String对象上,而`codePointAt`方法定义在字符串的实例对象上。
136+
上面代码中,如果`String.fromCharCode`方法有多个参数,则它们会被合并成一个字符串返回。
137+
138+
注意,`fromCodePoint`方法定义在`String`对象上,而`codePointAt`方法定义在字符串的实例对象上。
115139

116140
## 字符串的遍历器接口
117141

@@ -165,7 +189,7 @@ ES7提供了字符串实例的`at`方法,可以识别Unicode编号大于`0xFFF
165189

166190
## normalize()
167191

168-
为了表示语调和重音符号,Unicode提供了两种方法。一种是直接提供带重音符号的字符,比如Ǒ(\u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如`O`(\u004F)和`ˇ`(\u030C)合成`Ǒ`(\u004F\u030C)。
192+
为了表示语调和重音符号,Unicode提供了两种方法。一种是直接提供带重音符号的字符,比如`Ǒ`(\u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如`O`(\u004F)和`ˇ`(\u030C)合成`Ǒ`(\u004F\u030C)。
169193

170194
这两种表示方法,在视觉和语义上都等价,但是JavaScript不能识别。
171195

@@ -178,32 +202,32 @@ ES7提供了字符串实例的`at`方法,可以识别Unicode编号大于`0xFFF
178202

179203
上面代码表示,JavaScript将合成字符视为两个字符,导致两种表示方法不相等。
180204

181-
ES6提供`String.prototype.normalize()`方法,用来将字符的不同表示方法统一为同样的形式,这称为Unicode正规化。
205+
ES6提供字符串实例的`normalize()`方法,用来将字符的不同表示方法统一为同样的形式,这称为Unicode正规化。
182206

183207
```javascript
184208
'\u01D1'.normalize() === '\u004F\u030C'.normalize()
185209
// true
186210
```
187211

188-
normalize方法可以接受四个参数
212+
`normalize`方法可以接受四个参数
189213

190-
- NFC,默认参数,表示“标准等价合成”(Normalization Form Canonical Composition),返回多个简单字符的合成字符。所谓“标准等价”指的是视觉和语义上的等价。
191-
- NFD,表示“标准等价分解”(Normalization Form Canonical Decomposition),即在标准等价的前提下,返回合成字符分解的多个简单字符。
192-
- NFKC,表示“兼容等价合成”(Normalization Form Compatibility Composition),返回合成字符。所谓“兼容等价”指的是语义上存在等价,但视觉上不等价,比如“囍”和“喜喜”。
193-
- NFKD,表示“兼容等价分解”(Normalization Form Compatibility Decomposition),即在兼容等价的前提下,返回合成字符分解的多个简单字符。
214+
- `NFC`,默认参数,表示“标准等价合成”(Normalization Form Canonical Composition),返回多个简单字符的合成字符。所谓“标准等价”指的是视觉和语义上的等价。
215+
- `NFD`,表示“标准等价分解”(Normalization Form Canonical Decomposition),即在标准等价的前提下,返回合成字符分解的多个简单字符。
216+
- `NFKC`,表示“兼容等价合成”(Normalization Form Compatibility Composition),返回合成字符。所谓“兼容等价”指的是语义上存在等价,但视觉上不等价,比如“囍”和“喜喜”。(这只是用来举例,`normalize`方法不能识别中文。)
217+
- `NFKD`,表示“兼容等价分解”(Normalization Form Compatibility Decomposition),即在兼容等价的前提下,返回合成字符分解的多个简单字符。
194218

195219
```javascript
196220
'\u004F\u030C'.normalize('NFC').length // 1
197221
'\u004F\u030C'.normalize('NFD').length // 2
198222
```
199223

200-
上面代码表示,NFC参数返回字符的合成形式,NFD参数返回字符的分解形式
224+
上面代码表示,`NFC`参数返回字符的合成形式,`NFD`参数返回字符的分解形式
201225

202-
不过,normalize方法目前不能识别三个或三个以上字符的合成。这种情况下,还是只能使用正则表达式,通过Unicode编号区间判断。
226+
不过,`normalize`方法目前不能识别三个或三个以上字符的合成。这种情况下,还是只能使用正则表达式,通过Unicode编号区间判断。
203227

204228
## includes(), startsWith(), endsWith()
205229

206-
传统上,JavaScript只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6又提供了三种新方法。
230+
传统上,JavaScript只有`indexOf`方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6又提供了三种新方法。
207231

208232
- **includes()**:返回布尔值,表示是否找到了参数字符串。
209233
- **startsWith()**:返回布尔值,表示参数字符串是否在源字符串的头部。
@@ -227,11 +251,11 @@ s.endsWith('Hello', 5) // true
227251
s.includes('Hello', 6) // false
228252
```
229253

230-
上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束
254+
上面代码表示,使用第二个参数`n`时,`endsWith`的行为与其他两个方法有所不同。它针对前`n`个字符,而其他两个方法针对从第`n`个位置直到字符串结束
231255

232256
## repeat()
233257

234-
`repeat`方法返回一个新字符串,表示将原字符串重复n次
258+
`repeat`方法返回一个新字符串,表示将原字符串重复`n`
235259

236260
```javascript
237261
'x'.repeat(3) // "xxx"

0 commit comments

Comments
 (0)