mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 18:32:22 +00:00
edit string & promise
This commit is contained in:
parent
8ef1e5a876
commit
6c3396809c
@ -1,20 +1,22 @@
|
||||
# 二进制数组
|
||||
|
||||
二进制数组(ArrayBuffer对象、TypedArray对象、DataView对象)是JavaScript操作二进制数据的一个接口。这些对象早就存在,属于独立的规格,ES6将它们纳入了ECMAScript规格,并且增加了新的方法。
|
||||
二进制数组(ArrayBuffer对象、TypedArray视图和DataView视图)是JavaScript操作二进制数据的一个接口。这些对象早就存在,属于独立的规格,ES6将它们纳入了ECMAScript规格,并且增加了新的方法。
|
||||
|
||||
这个接口的原始设计目的,与WebGL项目有关。所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的、实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文本格式。文本格式传递一个32位整数,两端的JavaScript脚本与显卡都要进行格式转化,将非常耗时。这时要是存在一种机制,可以像C语言那样,直接操作字节,将4个字节的32位整数,以二进制形式原封不动地送入显卡,脚本的性能就会大幅提升。
|
||||
|
||||
二进制数组就是在这种背景下诞生的。它很像C语言的数组,允许开发者以数组下标的形式,直接操作内存,大大增强了JavaScript处理二进制数据的能力,使得开发者有可能通过JavaScript与操作系统的原生接口进行二进制通信。
|
||||
|
||||
二进制数组由三个对象组成。
|
||||
二进制数组由三类对象组成。
|
||||
|
||||
**(1)ArrayBuffer对象**:代表内存之中的一段二进制数据,可以通过“视图”进行操作。“视图”部署了数组接口,这意味着,可以用数组的方法操作内存。
|
||||
|
||||
**(2) TypedArray对象**:用来生成内存的视图,通过9个构造函数,可以生成9种数据格式的视图,比如Uint8Array(无符号8位整数)数组视图, Int16Array(16位整数)数组视图, Float32Array(32位浮点数)数组视图等等。
|
||||
**(2) TypedArray视图**:共包括9种类型的视图,比如Uint8Array(无符号8位整数)数组视图, Int16Array(16位整数)数组视图, Float32Array(32位浮点数)数组视图等等。
|
||||
|
||||
**(3)DataView对象**:用来生成内存的视图,可以自定义格式和字节序,比如第一个字节是Uint8(无符号8位整数)、第二、三个字节是Int16(16位整数)、第四个字节开始是Float32(32位浮点数)等等。
|
||||
**(3)DataView视图**:可以自定义复合格式的视图,比如第一个字节是Uint8(无符号8位整数)、第二、三个字节是Int16(16位整数)、第四个字节开始是Float32(32位浮点数)等等,此外还可以自定义字节序。
|
||||
|
||||
简单说,ArrayBuffer对象代表原始的二进制数据,TypedArray对象代表确定类型的二进制数据,DataView对象代表不确定类型的二进制数据。它们支持的数据类型一共有9种(DataView对象支持除Uint8C以外的其他8种)。
|
||||
简单说,ArrayBuffer对象代表原始的二进制数据,TypedArray视图用来读写简单类型的二进制数据,DataView视图用来读写复杂类型的二进制数据。
|
||||
|
||||
TypedArray视图支持的数据类型一共有9种(DataView视图支持除Uint8C以外的其他8种)。
|
||||
|
||||
数据类型 | 字节长度 | 含义 | 对应的C语言类型
|
||||
--------|--------|----|---------------
|
||||
@ -134,13 +136,13 @@ var v = new Int32Array(buffer);
|
||||
ArrayBuffer.isView(v) // true
|
||||
```
|
||||
|
||||
## TypedArray对象
|
||||
## TypedArray视图
|
||||
|
||||
### 概述
|
||||
|
||||
`ArrayBuffer`对象作为内存区域,可以存放多种类型的数据。同一段内存,不同数据有不同的解读方式,这就叫做“视图”(view)。`ArrayBuffer`有两种视图,一种是TypedArray视图,另一种是DataView视图,两者的区别主要是字节序,前者的数组成员都是同一个数据类型,后者的数组成员可以是不同的数据类型。
|
||||
`ArrayBuffer`对象作为内存区域,可以存放多种类型的数据。同一段内存,不同数据有不同的解读方式,这就叫做“视图”(view)。`ArrayBuffer`有两种视图,一种是TypedArray视图,另一种是DataView视图。前者的数组成员都是同一个数据类型,后者的数组成员可以是不同的数据类型。
|
||||
|
||||
目前,TypedArray对象一共提供9种类型的视图,每一种视图都是一种构造函数。
|
||||
目前,TypedArray视图一共包括9种类型,每一种视图都是一种构造函数。
|
||||
|
||||
- **Int8Array**:8位有符号整数,长度1个字节。
|
||||
- **Uint8Array**:8位无符号整数,长度1个字节。
|
||||
@ -152,7 +154,7 @@ ArrayBuffer.isView(v) // true
|
||||
- **Float32Array**:32位浮点数,长度4个字节。
|
||||
- **Float64Array**:64位浮点数,长度8个字节。
|
||||
|
||||
这9个构造函数生成的对象,统称为TypedArray对象。它们很像普通数组,都有`length`属性,都能用方括号运算符(`[]`)获取单个元素,所有数组的方法,在TypedArray数组上面都能使用。普通数组与TypedArray数组的差异主要在以下方面。
|
||||
这9个构造函数生成的数组,统称为TypedArray视图。它们很像普通数组,都有`length`属性,都能用方括号运算符(`[]`)获取单个元素,所有数组的方法,在它们上面都能使用。普通数组与TypedArray数组的差异主要在以下方面。
|
||||
|
||||
- `TypedArray`数组的所有成员,都是同一种类型。
|
||||
- `TypedArray`数组的成员是连续的,不会有空位。
|
||||
|
@ -322,7 +322,7 @@ yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历
|
||||
```javascript
|
||||
let generator = function* () {
|
||||
yield 1;
|
||||
yield* [2,3,4]; //use an iterable, is looped, and added as yields
|
||||
yield* [2,3,4];
|
||||
yield 5;
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,29 @@ import { stat, exists, readFile } from 'fs';
|
||||
|
||||
上面代码的实质是从`fs`模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”,即ES6可以在编译时就完成模块编译,效率要比CommonJS模块的加载方式高。
|
||||
|
||||
需要注意的是,ES6的模块自动采用严格模式,不管你有没有在模块头部加上`"use strict"`。
|
||||
## 严格模式
|
||||
|
||||
ES6的模块自动采用严格模式,不管你有没有在模块头部加上`"use strict"`。
|
||||
|
||||
严格模式主要有以下限制。
|
||||
|
||||
- 变量必须声明后再使用
|
||||
- 函数的参数不能有同名属性,否则报错
|
||||
- 不能使用`with`语句
|
||||
- 不能对只读属性赋值,否则报错
|
||||
- 不能使用前缀0表示八进制数,否则报错
|
||||
- 不能删除不可删除的属性,否则报错
|
||||
- 不能删除变量`delete prop`,会报错,只能删除属性`delete global[prop]`
|
||||
- `eval`不会在它的外层作用域引入变量
|
||||
- `eval`和`arguments`不能被重新赋值
|
||||
- `arguments`不会自动反映函数参数的变化
|
||||
- 不能使用`arguments.callee`
|
||||
- 不能使用`arguments.caller`
|
||||
- 禁止`this`指向全局对象
|
||||
- 不能使用`fn.caller`和`fn.arguments`获取函数调用的堆栈
|
||||
- 增加了保留字(比如`protected`、`static`和`interface`)
|
||||
|
||||
上面这些限制,模块都必须遵守。
|
||||
|
||||
## export命令
|
||||
|
||||
@ -60,9 +82,9 @@ export function multiply (x, y) {
|
||||
};
|
||||
```
|
||||
|
||||
上面代码对外输出一个函数multiply。
|
||||
上面代码对外输出一个函数`multiply`。
|
||||
|
||||
通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。
|
||||
通常情况下,`export`输出的变量就是本来的名字,但是可以使用`as`关键字重命名。
|
||||
|
||||
```javascript
|
||||
function v1() { ... }
|
||||
@ -79,6 +101,24 @@ export {
|
||||
|
||||
最后,`export`命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,下面的`import`命令也是如此。
|
||||
|
||||
```javascript
|
||||
function foo () {
|
||||
export default 'bar' // SyntaxError
|
||||
}
|
||||
foo()
|
||||
```
|
||||
|
||||
上面代码中,`export`语句放在函数之中,结果报错。
|
||||
|
||||
`export`语句输出的值是动态绑定,绑定其所在的模块。
|
||||
|
||||
```javascript
|
||||
export var foo = 'bar';
|
||||
setTimeout(() => foo = 'baz', 500);
|
||||
```
|
||||
|
||||
上面代码输出变量`foo`,值为`bar`,500毫秒之后变成`baz`。
|
||||
|
||||
## import命令
|
||||
|
||||
使用`export`命令定义了模块的对外接口以后,其他JS文件就可以通过`import`命令加载这个模块(文件)。
|
||||
@ -139,6 +179,14 @@ export v from "mod";
|
||||
export {v} from "mod";
|
||||
```
|
||||
|
||||
`import`语句会执行所加载的模块,因此可以有下面的写法。
|
||||
|
||||
```javascript
|
||||
import 'lodash'
|
||||
```
|
||||
|
||||
上面代码仅仅执行`lodash`模块,但是不输入任何值。
|
||||
|
||||
## 模块的整体加载
|
||||
|
||||
除了指定加载某个输出值,还可以使用整体加载,即用星号(`*`)指定一个对象,所有输出值都加载在这个对象上面。
|
||||
|
@ -134,9 +134,23 @@ var p2 = new Promise(function(resolve, reject){
|
||||
})
|
||||
```
|
||||
|
||||
上面代码中,p1和p2都是Promise的实例,但是p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。
|
||||
上面代码中,`p1`和`p2`都是Promise的实例,但是`p2`的`resolve`方法将`p1`作为参数,即一个异步操作的结果是返回另一个异步操作。
|
||||
|
||||
注意,这时p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是Pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是Resolved或者Rejected,那么p2的回调函数将会立刻执行。
|
||||
注意,这时`p1`的状态就会传递给`p2`,也就是说,`p1`的状态决定了`p2`的状态。如果`p1`的状态是`Pending`,那么`p2`的回调函数就会等待`p1`的状态改变;如果`p1`的状态已经是`Resolved`或者`Rejected`,那么`p2`的回调函数将会立刻执行。
|
||||
|
||||
```javascript
|
||||
var p1 = new Promise(function (resolve, reject) {
|
||||
setTimeout(() => reject(new Error('fail')), 3000)
|
||||
})
|
||||
var p2 = new Promise(function (resolve, reject) {
|
||||
setTimeout(() => resolve(p1), 1000)
|
||||
})
|
||||
p2.then(result => console.log(result))
|
||||
p2.catch(error => console.log(error))
|
||||
// Error: fail
|
||||
```
|
||||
|
||||
上面代码中,`p1`是一个Promise,3秒之后变为`rejected`。`p2`的状态由`p1`决定,1秒之后,`p2`调用`resolve`方法,但是此时`p1`的状态还没有改变,因此`p2`的状态也不会变。又过了2秒,`p1`变为`rejected`,`p2`也跟着变为`rejected`。
|
||||
|
||||
## Promise.prototype.then()
|
||||
|
||||
@ -349,19 +363,19 @@ someAsyncThing().then(function() {
|
||||
|
||||
## Promise.all()
|
||||
|
||||
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。
|
||||
`Promise.all`方法用于将多个Promise实例,包装成一个新的Promise实例。
|
||||
|
||||
```javascript
|
||||
var p = Promise.all([p1,p2,p3]);
|
||||
```
|
||||
|
||||
上面代码中,Promise.all方法接受一个数组作为参数,p1、p2、p3都是Promise对象的实例。(Promise.all方法的参数不一定是数组,但是必须具有iterator接口,且返回的每个成员都是Promise实例。)
|
||||
上面代码中,`Promise.all`方法接受一个数组作为参数,`p1`、`p2`、`p3`都是Promise对象的实例,如果不是,就会先调用下面讲到的`Promise.resolve`方法,将参数转为Promise实例,再进一步处理。(`Promise.all`方法的参数不一定是数组,但是必须具有iterator接口,且返回的每个成员都是Promise实例。)
|
||||
|
||||
p的状态由p1、p2、p3决定,分成两种情况。
|
||||
`p`的状态由`p1`、`p2`、`p3`决定,分成两种情况。
|
||||
|
||||
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
|
||||
(1)只有`p1`、`p2`、`p3`的状态都变成`fulfilled`,`p`的状态才会变成`fulfilled`,此时`p1`、`p2`、`p3`的返回值组成一个数组,传递给`p`的回调函数。
|
||||
|
||||
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
|
||||
(2)只要`p1`、`p2`、`p3`之中有一个被`rejected`,`p`的状态就变成`rejected`,此时第一个被`reject`的实例的返回值,会传递给`p`的回调函数。
|
||||
|
||||
下面是一个具体的例子。
|
||||
|
||||
@ -379,15 +393,30 @@ Promise.all(promises).then(function(posts) {
|
||||
```
|
||||
## Promise.race()
|
||||
|
||||
Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。
|
||||
`Promise.race`方法同样是将多个Promise实例,包装成一个新的Promise实例。
|
||||
|
||||
```javascript
|
||||
var p = Promise.race([p1,p2,p3]);
|
||||
```
|
||||
|
||||
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的回调函数。
|
||||
上面代码中,只要`p1`、`p2`、`p3`之中有一个实例率先改变状态,`p`的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给`p`的回调函数。
|
||||
|
||||
如果Promise.all方法和Promise.race方法的参数,不是Promise实例,就会先调用下面讲到的Promise.resolve方法,将参数转为Promise实例,再进一步处理。
|
||||
`Promise.race`方法的参数与`Promise.all`方法一样,如果不是Promise实例,就会先调用下面讲到的`Promise.resolve`方法,将参数转为Promise实例,再进一步处理。
|
||||
|
||||
下面是一个例子,如果指定时间内没有获得结果,就将Promise的状态变为`reject`,否则变为`resolve`。
|
||||
|
||||
```javascript
|
||||
var p = Promise.race([
|
||||
fetch('/resource-that-may-take-a-while'),
|
||||
new Promise(function (resolve, reject) {
|
||||
setTimeout(() => reject(new Error('request timeout')), 5000)
|
||||
})
|
||||
])
|
||||
p.then(response => console.log(response))
|
||||
p.catch(error => console.log(error))
|
||||
```
|
||||
|
||||
上面代码中,如果5秒之内`fetch`方法无法返回结果,变量`p`的状态就会变为`rejected`,从而触发`catch`方法指定的回调函数。
|
||||
|
||||
## Promise.resolve()
|
||||
|
||||
@ -397,7 +426,15 @@ var p = Promise.race([p1,p2,p3]);
|
||||
var jsPromise = Promise.resolve($.ajax('/whatever.json'));
|
||||
```
|
||||
|
||||
上面代码将jQuery生成deferred对象,转为一个新的Promise对象。
|
||||
上面代码将jQuery生成的`deferred`对象,转为一个新的Promise对象。
|
||||
|
||||
`Promise.resolve`等价于下面的写法。
|
||||
|
||||
```javascript
|
||||
Promise.resolve('foo')
|
||||
// 等价于
|
||||
new Promise(resolve => resolve('foo'))
|
||||
```
|
||||
|
||||
如果Promise.resolve方法的参数,不是具有then方法的对象(又称thenable对象),则返回一个新的Promise对象,且它的状态为Resolved。
|
||||
|
||||
@ -428,17 +465,17 @@ p.then(function () {
|
||||
|
||||
## Promise.reject()
|
||||
|
||||
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。
|
||||
`Promise.reject(reason)`方法也会返回一个新的Promise实例,该实例的状态为`rejected`。`Promise.reject`方法的参数`reason`,会被传递给实例的回调函数。
|
||||
|
||||
```javascript
|
||||
|
||||
var p = Promise.reject('出错了');
|
||||
// 等同于
|
||||
var p = new Promise((resolve, reject) => reject('foo'))
|
||||
|
||||
p.then(null, function (s){
|
||||
console.log(s)
|
||||
});
|
||||
// 出错了
|
||||
|
||||
```
|
||||
|
||||
上面代码生成一个Promise对象的实例p,状态为rejected,回调函数会立即执行。
|
||||
|
145
docs/string.md
145
docs/string.md
@ -11,7 +11,7 @@ JavaScript允许采用`\uxxxx`形式表示一个字符,其中“xxxx”表示
|
||||
// "a"
|
||||
```
|
||||
|
||||
但是,这种表示法只限于\u0000——\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表达。
|
||||
但是,这种表示法只限于`\u0000`——`\uFFFF`之间的字符。超出这个范围的字符,必须用两个双字节的形式表达。
|
||||
|
||||
```javascript
|
||||
"\uD842\uDFB7"
|
||||
@ -21,7 +21,7 @@ JavaScript允许采用`\uxxxx`形式表示一个字符,其中“xxxx”表示
|
||||
// " 7"
|
||||
```
|
||||
|
||||
上面代码表示,如果直接在“\u”后面跟上超过`0xFFFF`的数值(比如\u20BB7),JavaScript会理解成“\u20BB+7”。由于\u20BB是一个不可打印字符,所以只会显示一个空格,后面跟着一个7。
|
||||
上面代码表示,如果直接在“\u”后面跟上超过`0xFFFF`的数值(比如`\u20BB7`),JavaScript会理解成“\u20BB+7”。由于`\u20BB`是一个不可打印字符,所以只会显示一个空格,后面跟着一个7。
|
||||
|
||||
ES6对这一点做出了改进,只要将码点放入大括号,就能正确解读该字符。
|
||||
|
||||
@ -41,7 +41,7 @@ hell\u{6F} // 123
|
||||
|
||||
上面代码中,最后一个例子表明,大括号表示法与四字节的UTF-16编码是等价的。
|
||||
|
||||
有了这种表示法之后,JavaScript共有5种方法可以表示一个字符。
|
||||
有了这种表示法之后,JavaScript共有6种方法可以表示一个字符。
|
||||
|
||||
```javascript
|
||||
'\z' === 'z' // true
|
||||
@ -51,26 +51,6 @@ hell\u{6F} // 123
|
||||
'\u{7A}' === 'z' // true
|
||||
```
|
||||
|
||||
## String.fromCodePoint()
|
||||
|
||||
ES5提供String.fromCharCode方法,用于从码点返回对应字符,但是这个方法不能识别辅助平面的字符(编号大于0xFFFF)。
|
||||
|
||||
```javascript
|
||||
String.fromCharCode(0x20BB7)
|
||||
// "ஷ"
|
||||
```
|
||||
|
||||
上面代码中,最后返回码点U+0BB7对应的字符,而不是码点U+20BB7对应的字符。
|
||||
|
||||
ES6提供了String.fromCodePoint方法,可以识别0xFFFF的字符,弥补了String.fromCharCode方法的不足。在作用上,正好与codePointAt方法相反。
|
||||
|
||||
```javascript
|
||||
String.fromCodePoint(0x20BB7)
|
||||
// "𠮷"
|
||||
```
|
||||
|
||||
注意,fromCodePoint方法定义在String对象上,而codePointAt方法定义在字符串的实例对象上。
|
||||
|
||||
## codePointAt()
|
||||
|
||||
JavaScript内部,字符以UTF-16的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode码点大于0xFFFF的字符),JavaScript会认为它们是两个字符。
|
||||
@ -113,18 +93,70 @@ is32Bit("𠮷") // true
|
||||
is32Bit("a") // false
|
||||
```
|
||||
|
||||
## String.fromCodePoint()
|
||||
|
||||
ES5提供`String.fromCharCode`方法,用于从码点返回对应字符,但是这个方法不能识别辅助平面的字符(编号大于`0xFFFF`)。
|
||||
|
||||
```javascript
|
||||
String.fromCharCode(0x20BB7)
|
||||
// "ஷ"
|
||||
```
|
||||
|
||||
上面代码中,`String.fromCharCode`不能识别大于`0xFFFF`的码点,所以`0x20BB7`就发生了溢出,最高位`2`被舍弃了,最后返回码点`U+0BB7`对应的字符,而不是码点`U+20BB7`对应的字符。
|
||||
|
||||
ES6提供了`String.fromCodePoint`方法,可以识别`0xFFFF`的字符,弥补了`String.fromCharCode`方法的不足。在作用上,正好与`codePointAt`方法相反。
|
||||
|
||||
```javascript
|
||||
String.fromCodePoint(0x20BB7)
|
||||
// "𠮷"
|
||||
```
|
||||
|
||||
注意,`fromCodePoint`方法定义在String对象上,而`codePointAt`方法定义在字符串的实例对象上。
|
||||
|
||||
## 字符串的遍历器接口
|
||||
|
||||
ES6为字符串添加了遍历器接口(详见《Iterator》一章),使得字符串可以被`for...of`循环遍历。
|
||||
|
||||
```javascript
|
||||
for (let codePoint of 'foo') {
|
||||
console.log(codePoint)
|
||||
}
|
||||
// "f"
|
||||
// "o"
|
||||
// "o"
|
||||
```
|
||||
|
||||
除了遍历字符串,这个遍历器最大的优点是可以识别大于`0xFFFF`的码点,传统的`for`循环无法识别这样的码点。
|
||||
|
||||
```javascript
|
||||
var text = String.fromCodePoint(0x20BB7);
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
console.log(text[i]);
|
||||
}
|
||||
// " "
|
||||
// " "
|
||||
|
||||
for (let i of text) {
|
||||
console.log(i);
|
||||
}
|
||||
// "𠮷"
|
||||
```
|
||||
|
||||
上面代码中,字符串`text`只有一个字符,但是`for`循环会认为它包含两个字符(都不可打印),而`for...of`循环会正确识别出这一个字符。
|
||||
|
||||
## at()
|
||||
|
||||
ES5对字符串对象提供charAt方法,返回字符串给定位置的字符。该方法不能识别码点大于0xFFFF的字符。
|
||||
ES5对字符串对象提供`charAt`方法,返回字符串给定位置的字符。该方法不能识别码点大于`0xFFFF`的字符。
|
||||
|
||||
```javascript
|
||||
'abc'.charAt(0) // "a"
|
||||
'𠮷'.charAt(0) // "\uD842"
|
||||
```
|
||||
|
||||
上面代码中,charAt方法返回的是UTF-16编码的第一个字节,实际上是无法显示的。
|
||||
上面代码中,`charAt`方法返回的是UTF-16编码的第一个字节,实际上是无法显示的。
|
||||
|
||||
ES7提供了字符串实例的at方法,可以识别Unicode编号大于0xFFFF的字符,返回正确的字符。Chrome浏览器已经支持该方法。
|
||||
ES7提供了字符串实例的`at`方法,可以识别Unicode编号大于`0xFFFF`的字符,返回正确的字符。Chrome浏览器已经支持该方法。
|
||||
|
||||
```javascript
|
||||
'abc'.at(0) // "a"
|
||||
@ -133,7 +165,7 @@ ES7提供了字符串实例的at方法,可以识别Unicode编号大于0xFFFF
|
||||
|
||||
## normalize()
|
||||
|
||||
为了表示语调和重音符号,Unicode提供了两种方法。一种是直接提供带重音符号的字符,比如Ǒ(\u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如O(\u004F)和ˇ(\u030C)合成Ǒ(\u004F\u030C)。
|
||||
为了表示语调和重音符号,Unicode提供了两种方法。一种是直接提供带重音符号的字符,比如Ǒ(\u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如`O`(\u004F)和`ˇ`(\u030C)合成`Ǒ`(\u004F\u030C)。
|
||||
|
||||
这两种表示方法,在视觉和语义上都等价,但是JavaScript不能识别。
|
||||
|
||||
@ -146,7 +178,7 @@ ES7提供了字符串实例的at方法,可以识别Unicode编号大于0xFFFF
|
||||
|
||||
上面代码表示,JavaScript将合成字符视为两个字符,导致两种表示方法不相等。
|
||||
|
||||
ES6提供String.prototype.normalize()方法,用来将字符的不同表示方法统一为同样的形式,这称为Unicode正规化。
|
||||
ES6提供`String.prototype.normalize()`方法,用来将字符的不同表示方法统一为同样的形式,这称为Unicode正规化。
|
||||
|
||||
```javascript
|
||||
'\u01D1'.normalize() === '\u004F\u030C'.normalize()
|
||||
@ -178,32 +210,67 @@ normalize方法可以接受四个参数。
|
||||
- **endsWith()**:返回布尔值,表示参数字符串是否在源字符串的尾部。
|
||||
|
||||
```javascript
|
||||
var s = "Hello world!";
|
||||
var s = 'Hello world!';
|
||||
|
||||
s.startsWith("Hello") // true
|
||||
s.endsWith("!") // true
|
||||
s.includes("o") // true
|
||||
s.startsWith('Hello') // true
|
||||
s.endsWith('!') // true
|
||||
s.includes('o') // true
|
||||
```
|
||||
|
||||
这三个方法都支持第二个参数,表示开始搜索的位置。
|
||||
|
||||
```javascript
|
||||
var s = "Hello world!";
|
||||
var s = 'Hello world!';
|
||||
|
||||
s.startsWith("world", 6) // true
|
||||
s.endsWith("Hello", 5) // true
|
||||
s.includes("Hello", 6) // false
|
||||
s.startsWith('world', 6) // true
|
||||
s.endsWith('Hello', 5) // true
|
||||
s.includes('Hello', 6) // false
|
||||
```
|
||||
|
||||
上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
|
||||
|
||||
## repeat()
|
||||
|
||||
repeat()返回一个新字符串,表示将原字符串重复n次。
|
||||
`repeat`方法返回一个新字符串,表示将原字符串重复n次。
|
||||
|
||||
```javascript
|
||||
"x".repeat(3) // "xxx"
|
||||
"hello".repeat(2) // "hellohello"
|
||||
'x'.repeat(3) // "xxx"
|
||||
'hello'.repeat(2) // "hellohello"
|
||||
'na'.repeat(0) // ""
|
||||
```
|
||||
|
||||
参数如果是小数,会被取整。
|
||||
|
||||
```javascript
|
||||
'na'.repeat(2.9) // "nana"
|
||||
```
|
||||
|
||||
如果`repeat`的参数是负数或者`Infinity`,会报错。
|
||||
|
||||
```javascript
|
||||
'na'.repeat(Infinity)
|
||||
// RangeError
|
||||
'na'.repeat(-1)
|
||||
// RangeError
|
||||
```
|
||||
|
||||
但是,如果参数是0到-1之间的小数,则等同于0,这是因为会先进行取整运算。0到-1之间的小数,取整以后等于`-0`,`repeat`视同为0。
|
||||
|
||||
```javascript
|
||||
'na'.repeat(-0.9) // ""
|
||||
```
|
||||
|
||||
参数`NaN`等同于0。
|
||||
|
||||
```javascript
|
||||
'na'.repeat(NaN) // ""
|
||||
```
|
||||
|
||||
如果`repeat`的参数是字符串,则会先转换成数字。
|
||||
|
||||
```javascript
|
||||
'na'.repeat('na') // ""
|
||||
'na'.repeat('3') // "nanana"
|
||||
```
|
||||
|
||||
## 模板字符串
|
||||
|
Loading…
x
Reference in New Issue
Block a user