Skip to content

Commit bb853bb

Browse files
committed
complete url++
1 parent f81ef62 commit bb853bb

File tree

3 files changed

+84
-29
lines changed

3 files changed

+84
-29
lines changed

README.markdown

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -193,35 +193,35 @@
193193
- [例2:按键游戏](chapter7.markdown#a22)
194194
- [小结](chapter7.markdown#a23)
195195

196-
## [第八章 DOM和浏览器模式](chapter5.markdown)
197-
198-
- [分离关注点](chapter5.markdown#a2)
199-
- [DOM 脚本编程](chapter5.markdown#a3)
200-
- [DOM访问](chapter5.markdown#a4)
201-
- [DOM操作](chapter5.markdown#a5)
202-
- [事件](chapter5.markdown#a6)
203-
- [事件处理](chapter5.markdown#a7)
204-
- [事件委托](chapter5.markdown#a8)
205-
- [长时间运行的脚本](chapter5.markdown#a9)
206-
- [setTimeout()](chapter5.markdown#a10)
207-
- [Web Workers](chapter5.markdown#a11)
208-
- [远程脚本](chapter5.markdown#a12)
209-
- [XMLHttpRequest](chapter5.markdown#a13)
210-
- [JSONP](chapter5.markdown#a14)
211-
- [Frame和Image加载指示器](chapter5.markdown#a15)
212-
- [部署JavaScript](chapter5.markdown#a16)
213-
- [合并脚本](chapter5.markdown#a17)
214-
- [代码减肥和压缩](chapter5.markdown#a18)
215-
- [过期头](chapter5.markdown#a19)
216-
- [使用CDN](chapter5.markdown#a20)
217-
- [加载策略](chapter5.markdown#a21)
218-
- [script标签的位置](chapter5.markdown#a22)
219-
- [HTTP 分块](chapter5.markdown#a23)
220-
- [动态插入script标签非阻塞载入脚本](chapter5.markdown#a24)
221-
- [延迟加载](chapter5.markdown#a25)
222-
- [按需加载](chapter5.markdown#a26)
223-
- [预加载](chapter5.markdown#a27)
224-
- [小节](chapter5.markdown#a28)
196+
## [第八章 DOM和浏览器模式](chapter8.markdown)
197+
198+
- [分离关注点](chapter8.markdown#a2)
199+
- [DOM 脚本编程](chapter8.markdown#a3)
200+
- [DOM访问](chapter8.markdown#a4)
201+
- [DOM操作](chapter8.markdown#a5)
202+
- [事件](chapter8.markdown#a6)
203+
- [事件处理](chapter8.markdown#a7)
204+
- [事件委托](chapter8.markdown#a8)
205+
- [长时间运行的脚本](chapter8.markdown#a9)
206+
- [setTimeout()](chapter8.markdown#a10)
207+
- [Web Workers](chapter8.markdown#a11)
208+
- [远程脚本](chapter8.markdown#a12)
209+
- [XMLHttpRequest](chapter8.markdown#a13)
210+
- [JSONP](chapter8.markdown#a14)
211+
- [Frame和Image加载指示器](chapter8.markdown#a15)
212+
- [部署JavaScript](chapter8.markdown#a16)
213+
- [合并脚本](chapter8.markdown#a17)
214+
- [代码减肥和压缩](chapter8.markdown#a18)
215+
- [过期头](chapter8.markdown#a19)
216+
- [使用CDN](chapter8.markdown#a20)
217+
- [加载策略](chapter8.markdown#a21)
218+
- [script标签的位置](chapter8.markdown#a22)
219+
- [HTTP 分块](chapter8.markdown#a23)
220+
- [动态插入script标签非阻塞载入脚本](chapter8.markdown#a24)
221+
- [延迟加载](chapter8.markdown#a25)
222+
- [按需加载](chapter8.markdown#a26)
223+
- [预加载](chapter8.markdown#a27)
224+
- [小节](chapter8.markdown#a28)
225225

226226
## [索引](README.markdown)
227227

chapter5.markdown

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<a name="a1"></a>
12
# 对象创建模式
23

34
在JavaScript中创建对象很容易——可以通过使用对象直接量或者构造函数。本章将在此基础上介绍一些常用的对象创建模式。
@@ -6,6 +7,7 @@ JavaScript语言本身简单、直观,通常也没有其他语言那样的语
67

78
我们将对命名空间、依赖声明、模块模式以及沙箱模式进行初探——它们帮助更好地组织应用程序的代码,有效地减轻全局污染的问题。除此之外,还会对包括:私有和特权成员、静态和私有静态成员、对象常量、链以及类式函数定义方式在内的话题进行讨论。
89

10+
<a name="a2"></a>
911
## 命名空间模式(Namespace Pattern)
1012

1113
命名空间可以帮助减少全局变量的数量,与此同时,还能有效地避免命名冲突、名称前缀的滥用。
@@ -59,6 +61,7 @@ JavaScript默认语法并不支持命名空间,但很容易可以实现此特
5961
本章后续要介绍的沙箱模式则可以避免这些缺点。
6062

6163

64+
<a name="a3"></a>
6265
###通用命名空间函数
6366

6467
随着程序复杂度的提高,代码会分置在不同的文件中以特定顺序来加载,这样一来,就不能保证你的代码一定是第一个申明命名空间或者改变量下的属性的。甚至还会发生属性覆盖的问题。所以,在创建命名空间或者添加属性的时候,最好先检查下是否存在,如下所示:
@@ -125,6 +128,7 @@ JavaScript默认语法并不支持命名空间,但很容易可以实现此特
125128

126129
图5-1 MYAPP命名空间在Firebug下的可视结果
127130

131+
<a name="a4"></a>
128132
## 声明依赖
129133

130134
JavaScript库往往是模块化而且有用到命名空间的,这使用你可以只使用你需要的模块。比如在YUI2中,全局变量YAHOO就是一个命名空间,各个模块作为全局变量的属性,比如YAHOO.util.Dom(DOM模块)、YAHOO.util.Event(事件模块)。
@@ -173,6 +177,7 @@ JavaScript库往往是模块化而且有用到命名空间的,这使用你可
173177
*/
174178

175179

180+
<a name="a5"></a>
176181
## 私有属性和方法
177182

178183
JavaScript不像Java或者其它语言,它没有专门的提供私有、保护、公有属性和方法的语法。所有的对象成员都是公有的:
@@ -196,6 +201,7 @@ JavaScript不像Java或者其它语言,它没有专门的提供私有、保护
196201
var toy = new Gadget();
197202
console.log(toy.name); // `name` is public console.log(toy.stretch()); // stretch() is public
198203

204+
<a name="a6"></a>
199205
### 私有成员
200206

201207
尽管语言并没有用于私有成员的专门语法,但你可以通过闭包来实现。在构造函数中创建一个闭包,任何在这个闭包中的部分都不会暴露到构造函数之外。但是,这些私有变量却可以被公有方法访问,也就是在构造函数中定义的并且作为返回对象一部分的那些方法。我们来看一个例子,name是一个私有成员,在构造函数之外不能被访问:
@@ -217,12 +223,14 @@ JavaScript不像Java或者其它语言,它没有专门的提供私有、保护
217223

218224
如你所见,在JavaScript创建私有成员很容易。你需要做的只是将私有成员放在一个函数中,保证它是函数的本地变量,也就是说让它在函数之外不可以被访问。
219225

226+
<a name="a7"></a>
220227
### 特权方法
221228

222229
特权方法的概念不涉及到任何语法,它只是一个给可以访问到私有成员的公有方法的名字(就像它们有更多权限一样)。
223230

224231
在前面的例子中,getName()就是一个特权方法,因为它有访问name属性的特殊权限。
225232

233+
<a name="a8"></a>
226234
### 私有成员失效
227235

228236
当你使用私有成员时,需要考虑一些极端情况:
@@ -266,6 +274,7 @@ JavaScript不像Java或者其它语言,它没有专门的提供私有、保护
266274

267275
当你需要传递所有的数据时,有另外一种方法,就是使用通用的对象复制函数创建specs对象的一个副本。下一章提供了两个这样的函数——一个叫extend(),它会浅复制一个给定的对象(只复制顶层的成员)。另一个叫extendDeep(),它会做深复制,遍历所有的属性和嵌套的属性。
268276

277+
<a name="a9"></a>
269278
### 对象字面量和私有成员
270279

271280
到目前为止,我们只看了使用构建函数创建私有成员的示例。如果使用对象字面量创建对象时会是什么情况呢?是否有可能含有私有成员?
@@ -307,6 +316,7 @@ JavaScript不像Java或者其它语言,它没有专门的提供私有、保护
307316

308317
这个例子也是所谓的“模块模式”的基础,我们稍后将讲到它。
309318

319+
<a name="a10"></a>
310320
### 原型和私有成员
311321

312322
使用构造函数创建私有成员的一个弊端是,每一次调用构造函数创建对象时这些私有成员都会被创建一次。
@@ -338,6 +348,7 @@ JavaScript不像Java或者其它语言,它没有专门的提供私有、保护
338348
var toy = new Gadget();
339349
console.log(toy.getName()); // privileged "own" method console.log(toy.getBrowser()); // privileged prototype method
340350

351+
<a name="a11"></a>
341352
### 将私有函数暴露为公有方法
342353

343354
“暴露模式”是指将已经有的私有函数暴露为公有方法。当对对象进行操作时,所有功能代码都对这些操作很敏感,而你想尽量保护这些代码的时候很有用。(译注:指对来自外部的修改很敏感。)但同时,你又希望能提供一些功能的访问权限,因为它们会被用到。如果你把这些方法公开,就会使得它们不再健壮,你的API的使用者可能修改它们。在ECMAScript5中,你可以选择冻结一个对象,但在之前的版本中不可用。下面进入暴露模式(原来是由Christian Heilmann创造的模式,叫“暴露模块模式”)。
@@ -386,6 +397,7 @@ JavaScript不像Java或者其它语言,它没有专门的提供私有、保护
386397
myarray.indexOf = null;
387398
myarray.inArray(["a", "b", "z"], "z"); // 2
388399

400+
<a name="a12"></a>
389401
## 模块模式
390402

391403
模块模式使用得很广泛,因为它可以为代码提供特定的结构,帮助组织日益增长的代码。不像其它语言,JavaScript没有专门的“包”(package)的语法,但模块模式提供了用于创建独立解耦的代码片段的工具,这些代码可以被当成黑盒,当你正在写的软件需求发生变化时,这些代码可以被添加、替换、移除。
@@ -462,6 +474,7 @@ MYAPP.utilities.array = (function () {
462474

463475
模块模式被广泛使用,这是一种值得强烈推荐的模式,它可以帮助组织代码,尤其是代码量在不断增长的时候。
464476

477+
<a name="a13"></a>
465478
### 暴露模块模式
466479

467480
我们在本章中讨论私有成员模式时已经讨论过暴露模式。模块模式也可以用类似的方法来组织,将所有的方法保持私有,只在最后暴露需要使用的方法来初始化API。
@@ -495,6 +508,7 @@ MYAPP.utilities.array = (function () {
495508
};
496509
}());
497510

511+
<a name="a14"></a>
498512
### 创建构造函数的模块
499513

500514
前面的例子创建了一个对象`MYAPP.utilities.array`,但有时候使用构造函数来创建对象会更方便。你也可以同样使用模块模式来做。唯一的区别是包裹模块的立即执行的函数会在最后返回一个函数,而不是一个对象。
@@ -542,6 +556,7 @@ MYAPP.utilities.array = (function () {
542556

543557
var arr = new MYAPP.utilities.Array(obj);
544558

559+
<a name="a15"></a>
545560
### 在模块中引入全局上下文
546561

547562
作为这种模式的一个常见的变种,你可以给包裹模块的立即执行的函数传递参数。你可以传递任何值,但通常会传递全局变量甚至是全局对象本身。引入全局上下文可以加快函数内部的全局变量的解析,因为引入之后会作为函数的本地变量:
@@ -554,6 +569,7 @@ MYAPP.utilities.array = (function () {
554569
555570
}(MYAPP, this));
556571

572+
<a name="a16"></a>
557573
## 沙箱模式
558574

559575
沙箱模式主要着眼于命名空间模式的短处,即:
@@ -565,6 +581,7 @@ MYAPP.utilities.array = (function () {
565581

566582
这个模式在YUI3中用得很多,但是需要记住的是,下面的讨论只是一些示例实现,并不讨论YUI3中的消息箱是如何实现的。
567583

584+
<a name="a17"></a>
568585
### 全局构造函数
569586

570587
在命名空间模式中 ,有一个全局对象,而在沙箱模式中,唯一的全局变量是一个构造函数,我们把它命名为`Sandbox()`。我们使用这个构造函数来创建对象,同时也要传入一个回调函数,这个函数会成为代码运行的独立空间。
@@ -633,6 +650,7 @@ MYAPP.utilities.array = (function () {
633650

634651
现在我们来看一下如何实现`Sandbox()`构造函数和它的模块来支持上面讲到的所有功能。
635652

653+
<a name="a18"></a>
636654
### 添加模块
637655

638656
在动手实现构造函数之前,我们来看一下如何添加模块。
@@ -663,6 +681,7 @@ MYAPP.utilities.array = (function () {
663681

664682
实现每个模块功能的函数接受一个实例`box`作为参数,并给这个实例添加属性和方法。
665683

684+
<a name="a19"></a>
666685
### 实现构造函数
667686

668687
最后,我们来实现`Sandbox()`构造函数(你可能会很自然地想将这类构造函数命名为对你的类库或者应用有意义的名字):
@@ -722,10 +741,12 @@ MYAPP.utilities.array = (function () {
722741
- 当我们知道依赖的模块之后就初始化它们,也就是调用实现每个模块的函数。
723742
- 构造函数的最后一个参数是回调函数。这个回调函数会在最后使用新创建的实例来调用。事实上这个回调函数就是用户的沙箱,它被传入一个`box`对象,这个对象包含了所有依赖的功能。
724743

744+
<a name="a20"></a>
725745
## 静态成员
726746

727747
静态属性和方法是指那些在所有的实例中保持一致的成员。在基于类的语言中,表态成员是用专门的语法来创建,使用时就像是类自己的成员一样。比如`MathUtils`类的`max()`方法会被像这样调用:`MathUtils.max(3, 5)`。这是一个公有静态成员的示例,即可以在不实例化类的情况下使用。同样也可以有私有的静态方法,即对类的使用者不可见,而在类的所有实例间是共享的。我们来看一下如何在JavaScript中实现公有和私有静态成员。
728748

749+
<a name="a21"></a>
729750
### 公有静态成员
730751

731752
在JavaScript中没有专门用于静态成员的语法。但通过给构造函数添加属性的方法,可以拥有和基于类的语言一样的使用语法。之所有可以这样做是因为构造函数和其它的函数一样,也是对象,可以拥有属性。前一章讨论过的Memoization模式也使用了同样的方法,即给函数添加属性。
@@ -800,6 +821,7 @@ MYAPP.utilities.array = (function () {
800821
var a = new Gadget('499.99');
801822
a.isShiny(); // "you bet, it costs $499.99!"
802823

824+
<a name="a22"></a>
803825
### 私有静态成员
804826

805827
到目前为止,我们都只讨论了公有的静态方法,现在我们来看一下如何实现私有静态成员。所谓私有静态成员是指:
@@ -864,6 +886,7 @@ MYAPP.utilities.array = (function () {
864886

865887
静态属性(包括私有和公有)有时候会非常方便,它们可以包含和具体实例无关的方法和数据,而不用在每次实例中再创建一次。当我们在第七章中讨论单例模式时,你可以看到使用静态属性实现类式单例构造函数的例子。
866888

889+
<a name="a23"></a>
867890
## 对象常量
868891

869892
JavaScript中是没有常量的,尽管在一些比较现代的环境中可能会提供`const`来创建常量。
@@ -952,6 +975,7 @@ JavaScript中是没有常量的,尽管在一些比较现代的环境中可能
952975
// is the value still intact?
953976
constant.get("maxwidth"); // 480
954977

978+
<a name="a24"></a>
955979
## 链式调用模式
956980

957981
使用链式调用模式可以让你在一对个象上连续调用多个方法,不需要将前一个方法的返回值赋给变量,也不需要将多个方法调用分散在多行:
@@ -983,6 +1007,7 @@ JavaScript中是没有常量的,尽管在一些比较现代的环境中可能
9831007
obj.add(3);
9841008
obj.shout(); // 5
9851009

1010+
<a name="a25"></a>
9861011
### 链式调用模式的利弊
9871012

9881013
使用链式调用模式的一个好处就是可以节省代码量,使得代码更加简洁和易读,读起来就像在读句子一样。
@@ -995,6 +1020,7 @@ JavaScript中是没有常量的,尽管在一些比较现代的环境中可能
9951020

9961021
document.getElementsByTagName('head')[0].appendChild(newnode);
9971022

1023+
<a name="a26"></a>
9981024
## method()方法
9991025

10001026
JavaScript对于习惯于用类来思考的人来说可能会比较费解,这也是很多开发者希望将JavaScript代码变得更像基于类的语言的原因。其中的一种尝试就是由Douglas Crockford提出来的`method()`方法。其实,他也承认将JavaScript变得像基于类的语言是不推荐的方法,但不管怎样,这都是一种有意思的模式,你可能会在一些应用中见到。
@@ -1044,6 +1070,7 @@ JavaScript对于习惯于用类来思考的人来说可能会比较费解,这
10441070

10451071
`method()`的实现中,我们首先检查这个方法是否已经被实现过,如果没有则继续,将传入的参数`implementation`加到构造函数的原型中。在这里`this`指向构造函数,而我们要增加的功能正在在这个构造函数的原型上。
10461072

1073+
<a name="a27"></a>
10471074
## 小结
10481075

10491076
在本章中你看到了好几种除了字面量和构造函数之外的创建对象的方法。

0 commit comments

Comments
 (0)