Skip to content

Commit 043a06a

Browse files
committed
修改stdlib/json
1 parent d608790 commit 043a06a

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

advanced/asynchronous.md

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
---
2-
title: JavaScript异步编程的模式
2+
title: Promise对象
33
layout: page
44
category: advanced
55
date: 2012-12-22
66
modifiedOn: 2013-11-28
77
---
88

9-
## 概述
9+
## JavaScript的异步执行
10+
11+
### 概述
1012

1113
Javascript语言的执行环境是"单线程"(single thread)。所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
1214

@@ -20,7 +22,7 @@ Javascript语言的执行环境是"单线程"(single thread)。所谓"单线
2022

2123
以下总结了"异步模式"编程的4种方法,理解它们可以让你写出结构更合理、性能更出色、维护更方便的JavaScript程序。
2224

23-
## 回调函数
25+
### 回调函数
2426

2527
回调函数是异步编程最基本的方法。
2628

@@ -57,9 +59,9 @@ f1(f2);
5759

5860
采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。
5961

60-
回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度[耦合](http://en.wikipedia.org/wiki/Coupling_(computer_programming)(Coupling),使得程序结构混乱、流程难以追踪(尤其是回调函数嵌套的情况),而且每个任务只能指定一个回调函数。
62+
回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度[耦合](http://en.wikipedia.org/wiki/Coupling_(computer_programming))(Coupling),使得程序结构混乱、流程难以追踪(尤其是回调函数嵌套的情况),而且每个任务只能指定一个回调函数。
6163

62-
## 事件监听
64+
### 事件监听
6365

6466
另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
6567

@@ -88,7 +90,7 @@ f1.trigger('done')表示,执行完成后,立即触发done事件,从而开
8890

8991
这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"[去耦合](http://en.wikipedia.org/wiki/Decoupling)"(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
9092

91-
## 发布/订阅
93+
### 发布/订阅
9294

9395
"事件"完全可以理解成"信号",如果存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"[发布/订阅模式](http://en.wikipedia.org/wiki/Publish-subscribe_pattern)"(publish-subscribe pattern),又称"[观察者模式](http://en.wikipedia.org/wiki/Observer_pattern)"(observer pattern)。
9496

@@ -127,7 +129,7 @@ jQuery.unsubscribe("done", f2);
127129

128130
这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。
129131

130-
## Promises对象
132+
## Promise对象
131133

132134
### 简介
133135

@@ -174,12 +176,16 @@ step1(function (value1) {
174176

175177
Promises原本只是社区提出的一个构想,一些外部函数库率先实现了这个功能,目前ECMAScript 6正在考虑将其写入语言标准,Chrome和Firefox浏览器的最新版本都初步部署了这个功能。
176178

177-
### Promises接口
179+
### Promise接口
178180

179181
当异步任务返回一个promise对象(小写表示这是Promise的实例)时,该对象只有三种状态:未完成(pending)、已完成(fulfilled)、失败(rejected)。
180182

181183
这三种的状态的变化途径只有两个,且只能发生一次:从“未完成”到“已完成”,或者从“未完成”到“失败”。一旦当前状态变为“已完成”或“失败”,就意味着不会再发生状态变化了。
182184

185+
Promise对象的运行结果,最终只有两种。
186+
187+
- 得到一个值,状态变为fulfilled
188+
- 抛出一个错误,状态变为rejected
183189

184190
promise对象的then方法用来添加回调函数。它可以接受两个回调函数,第一个是操作成功(fulfilled)时的回调函数,第二个是操作失败(rejected)时的回调函数(可以不提供)。一旦状态改变,就调用相应的回调函数。
185191

@@ -197,6 +203,24 @@ promise对象的then方法用来添加回调函数。它可以接受两个回调
197203

198204
console.log和console.error这两个最后的回调函数,用法上有一点重要的区别。console.log只显示回调函数step4的返回值,而console.error可以显示step2、step3、step4之中任何一个发生的错误。也就是说,假定step2操作失败,抛出一个错误,这时step3和step4都不会再运行了,promises对象开始寻找接下来的第一个错误回调函数,在上面代码中是console.error。所以,结论就是Promises对象的错误有传递性。
199205

206+
换言之,上面的代码等同于下面的形式。
207+
208+
```javascript
209+
210+
try {
211+
var v1 = step1();
212+
var v2 = step2(v1);
213+
var v3 = step3(v2);
214+
var v4 = step4(v3);
215+
console.log(v4);
216+
} catch (error) {
217+
console.error(error);
218+
}
219+
220+
```
221+
222+
上面代码表示,try部分任何一步的错误,都会被catch部分捕获,并导致整个Promise操作的停止。
223+
200224
### Promises对象的实现
201225

202226
Promises只是一个规范,JavaScript语言原生还未提供支持。一般来说,总是选用现成的函数库。为了真正理解Promises对象,下面我们自己动手写一个Promises的实现。

stdlib/json.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ JSON.stringify({ name: "张三" })
8787

8888
上面代码将各种类型的值,转成JSON字符串。需要注意的是,对于原始类型的字符串,转换结果会带双引号,即字符串`abc`会被转成`"abc"`,这是因为将来还原的时候,双引号可以让JavaScript引擎知道,abc是一个字符串,而不是一个变量名。
8989

90-
如果原始对象中,有一个成员的值是undefined、函数或XML对象,这个成员会被省略。如果该值是数组的成员,则返回null
90+
如果原始对象中,有一个成员的值是undefined、函数或XML对象,这个成员会被省略。如果数组的成员是undefined、函数或XML对象,则这些值被转成null
9191

9292
{% highlight javascript %}
9393

@@ -101,6 +101,14 @@ JSON.stringify({
101101

102102
上面代码中,原始对象的f属性是一个函数,JSON.stringify方法返回的字符串会将这个属性省略。而a属性是一个数组,成员分别为函数和undefined,它们都被转成了null。
103103

104+
正则对象会被转成空对象。
105+
106+
```javascript
107+
108+
JSON.stringify(/foo/) // "{}"
109+
110+
```
111+
104112
JSON.stringify方法还可以接受一个数组参数,指定需要转成字符串的属性。
105113

106114
{% highlight javascript %}
@@ -225,7 +233,7 @@ var o = {
225233
}
226234
};
227235
var json = JSON.stringify({x: o});
228-
// '{"x":"bar"}'.
236+
// '{"x":"bar"}'
229237

230238
{% endhighlight %}
231239

@@ -238,6 +246,19 @@ JSON.stringify(new Date("2011-07-29"))
238246

239247
{% endhighlight %}
240248

249+
toJSON方法的一个应用是,可以将正则对象自动转为字符串。
250+
251+
```javascript
252+
253+
RegExp.prototype.toJSON = RegExp.prototype.toString;
254+
255+
JSON.stringify(/foo/)
256+
// "/foo/"
257+
258+
```
259+
260+
上面代码,在正则对象的原型上面部署了toJSON方法,将其指向toString方法,因此遇到转换成JSON时,就正则对象就先调用toJSON方法转为字符串,然后再被JSON.stingify方法处理。
261+
241262
### JSON.parse()
242263

243264
JSON.parse方法用于将JSON字符串转化成对象。

0 commit comments

Comments
 (0)