-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path10_modules.html
More file actions
728 lines (705 loc) · 56.7 KB
/
Copy path10_modules.html
File metadata and controls
728 lines (705 loc) · 56.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
<!doctype html>
<head>
<meta charset="utf-8">
<title>Modules :: Eloquent JavaScript</title>
<link rel=stylesheet href="js/node_modules/codemirror/lib/codemirror.css">
<script src="js/acorn_codemirror.js"></script>
<link rel=stylesheet href="css/ejs.css">
<script src="js/sandbox.js"></script>
<script src="js/ejs.js"></script>
<script>var chapNum = 10;var sandboxLoadFiles = ["code/chapter/10_modules.js", "code/loadfile.js"];</script>
</head>
<article>
<nav>
<a href="09_regexp.html" title="previous chapter">◀</a>
<a href="index.html" title="cover">◆</a>
<a href="11_language.html" title="next chapter">▶</a>
</nav>
<h1><div class=chap_num>Chapter 10</div>Modules</h1>
<blockquote>
<p><a class=p_ident id="p_PJiK2g1JXC" href="#p_PJiK2g1JXC"></a>A beginning programmer writes her programs like an ant builds her
hill, one piece at a time, without thought for the bigger structure.
Her programs will be like loose sand. They may stand for a while, but
growing too big they fall apart.</p>
<p><a class=p_ident id="p_OfZWeuo+oF" href="#p_OfZWeuo+oF"></a>Realizing this problem, the programmer will start to spend a lot of
time thinking about structure. Her programs will be rigidly
structured, like rock sculptures. They are solid, but when they must
change, violence must be done to them.</p>
<p><a class=p_ident id="p_fFMEGH1dk3" href="#p_fFMEGH1dk3"></a>The master programmer knows when to apply structure and when to leave
things in their simple form. Her programs are like clay, solid yet
malleable.</p>
<footer>Master Yuan-Ma, <cite>The Book of Programming</cite></footer>
</blockquote>
<p><a class=p_ident id="p_1aMUBkVbPd" href="#p_1aMUBkVbPd"></a>Every program has a shape. On
a small scale, this shape is determined by its division into
functions and the blocks inside those functions. Programmers have
a lot of freedom in the way they structure their programs. Shape follows
more from the taste of the programmer than from the program’s
intended functionality.</p>
<p><a class=p_ident id="p_NOETmtvWWx" href="#p_NOETmtvWWx"></a>When looking at a larger program in its entirety,
individual functions start to blend into the background. Such a
program can be made more readable if we have a larger unit of
organization.</p>
<p><a class=p_ident id="p_07zdYJYQ1M" href="#p_07zdYJYQ1M"></a><em>Modules</em> divide programs into clusters of code that, by <em>some</em>
criterion, belong together. This chapter explores some of the benefits
that such division provides and shows techniques for building
modules in JavaScript.</p>
<h2><a class=h_ident id="h_0DSW4+9YVh" href="#h_0DSW4+9YVh"></a>Why modules help</h2>
<p><a class=p_ident id="p_ovuaejexnJ" href="#p_ovuaejexnJ"></a>There are a number of reasons why
authors divide their books into chapters and sections. These
divisions make it easier for a reader to see how the book is built up
and to find specific parts that they are interested in. They also help
the <em>author</em> by providing a clear focus for every section.</p>
<p><a class=p_ident id="p_QxCtWUR2zJ" href="#p_QxCtWUR2zJ"></a>The benefits of organizing a program into several files or
modules are similar. Structure helps people who aren’t yet
familiar with the code find what they are looking for and makes it
easier for the programmer to keep things that are related
close together.</p>
<p><a class=p_ident id="p_4vnN7lCDZy" href="#p_4vnN7lCDZy"></a>Some
programs are even organized along the model of a traditional text,
with a well-defined order in which the reader is encouraged to go
through the program and with lots of prose (comments) providing a coherent
description of the code. This makes reading the program a lot less
intimidating—reading unknown code is usually intimidating—but has the
downside of being more work to set up. It also makes the program more
difficult to change because prose tends to be more tightly
interconnected than code. This style is called <em>literate programming</em>. The “project” chapters of this book can be considered
literate programs.</p>
<p><a class=p_ident id="p_Ou/d4KbIy/" href="#p_Ou/d4KbIy/"></a>As a
general rule, structuring things costs energy. In the early stages of
a project, when you are not quite sure yet what goes where or what
kind of modules the program needs at all, I endorse a minimalist,
structureless attitude. Just put everything wherever it is convenient
to put it until the code stabilizes. That way, you won’t be wasting
time moving pieces of the program back and forth, and you won’t
accidentally lock yourself into a structure that does not actually fit
your program.</p>
<h3><a class=h_ident id="h_NitCO6r9Hn" href="#h_NitCO6r9Hn"></a>Namespacing</h3>
<p><a class=p_ident id="p_8S/+Hon3uA" href="#p_8S/+Hon3uA"></a>Most modern programming languages have a
scope level between <em>global</em> (everyone can see it) and <em>local</em>
(only this function can see it). JavaScript does not. Thus, by
default, everything that needs to be visible outside of the scope of a
top-level function is visible <em>everywhere</em>.</p>
<p><a class=p_ident id="p_QMB7RIsBay" href="#p_QMB7RIsBay"></a>Namespace pollution, the problem of a lot of
unrelated code having to share a single set of global variable names,
was mentioned in <a href="04_data.html#namespace_pollution">Chapter 4</a>,
where the <code>Math</code> object was given as an example of an object that acts
like a module by grouping math-related functionality.</p>
<p><a class=p_ident id="p_bBKNVkrywA" href="#p_bBKNVkrywA"></a>Though JavaScript provides no actual
module construct yet, objects can be used to create publicly
accessible subnamespaces, and functions can be used to create an
isolated, private namespace inside of a module. Later in this chapter,
I will discuss a way to build reasonably convenient, namespace-isolating
modules on top of the primitive concepts that JavaScript gives us.</p>
<h3><a class=h_ident id="h_UuxJID5Z2e" href="#h_UuxJID5Z2e"></a>Reuse</h3>
<p><a class=p_ident id="p_0MwF7DbAP0" href="#p_0MwF7DbAP0"></a>In a “flat” project, which isn’t
structured as a set of modules, it is not apparent which parts of
the code are needed to use a particular function. In my program for
spying on my enemies (see <a href="09_regexp.html#ini">Chapter 9</a>), I wrote
a function for reading configuration files. If I want to use that
function in another project, I must go and copy out the parts of the
old program that look like they are relevant to the functionality that
I need and paste them into my new program. Then, if I find a mistake
in that code, I’ll fix it only in whichever program that I’m working
with at the time and forget to also fix it in the other program.</p>
<p><a class=p_ident id="p_n5Itkf6SsY" href="#p_n5Itkf6SsY"></a>Once you have lots of such shared, duplicated pieces
of code, you will find yourself wasting a lot of time and energy on
moving them around and keeping them up-to-date.</p>
<p><a class=p_ident id="p_zwgHmRoxk9" href="#p_zwgHmRoxk9"></a>Putting pieces of functionality that stand on their own
into separate files and modules makes them easier to track, update,
and share because all the various pieces of code that want to use the
module load it from the same actual file.</p>
<p><a class=p_ident id="p_D2yYhnbA9K" href="#p_D2yYhnbA9K"></a>This
idea gets even more powerful when the relations between modules—which
other modules each module depends on—are explicitly stated. You can
then automate the process of installing and upgrading external modules
(<em>libraries</em>).</p>
<p><a class=p_ident id="p_3ED8vjm59N" href="#p_3ED8vjm59N"></a>Taking this idea even
further, imagine an online service that tracks and distributes
hundreds of thousands of such libraries, allowing you to search for
the functionality you need and, once you find it, set up your project
to automatically download it.</p>
<p id="modules_npm"><a class=p_ident id="p_8hHGZUvmtE" href="#p_8hHGZUvmtE"></a>This service exists. It is called NPM
(<a href="http://npmjs.org"><em>npmjs.org</em></a>). NPM consists of an online database of
modules and a tool for downloading and upgrading the modules your
program depends on. It grew out of Node.js, the browserless
JavaScript environment we will discuss in
<a href="20_node.html#node">Chapter 20</a>, but can also be useful when
programming for the browser.</p>
<h3><a class=h_ident id="h_qJacYNwWWL" href="#h_qJacYNwWWL"></a>Decoupling</h3>
<p><a class=p_ident id="p_BIr3LxVodJ" href="#p_BIr3LxVodJ"></a>Another important role of modules is isolating pieces
of code from each other, in the same way that the object interfaces
from <a href="06_object.html#interface">Chapter 6</a> do. A well-designed
module will provide an interface for external code to use. As the
module gets updated with bug fixes and new functionality, the
existing interface stays the same (it is <em>stable</em>) so that other
modules can use the new, improved version without any changes to
themselves.</p>
<p><a class=p_ident id="p_B3JCtLjLbo" href="#p_B3JCtLjLbo"></a>Note that a stable interface does not mean no new
functions, methods, or variables are added. It just means that
existing functionality isn’t removed and its meaning is not changed.</p>
<p><a class=p_ident id="p_vcubl5qb7a" href="#p_vcubl5qb7a"></a>A good module
interface should allow the module to grow without breaking the old
interface. This means exposing as few of the module’s internal
concepts as possible while also making the “language” that the
interface exposes powerful and flexible enough to be applicable in a
wide range of situations.</p>
<p><a class=p_ident id="p_jT10dBy1PO" href="#p_jT10dBy1PO"></a>For interfaces that expose a single, focused
concept, such as a configuration file reader, this design comes
naturally. For others, such as a text editor, which has many different
aspects that external code might need to access (content, styling,
user actions, and so on), it requires careful design.</p>
<h2><a class=h_ident id="h_FIe+oM6Cvt" href="#h_FIe+oM6Cvt"></a>Using functions as namespaces</h2>
<p><a class=p_ident id="p_Qi0v4Dtc05" href="#p_Qi0v4Dtc05"></a>Functions are the only things in
JavaScript that create a new scope. So if we want our modules
to have their own scope, we will have to base them on functions.</p>
<p><a class=p_ident id="p_TJhIvzABX+" href="#p_TJhIvzABX+"></a>Consider this
trivial module for associating names with day-of-the-week numbers, as
returned by a <code>Date</code> object’s <code>getDay</code> method:</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_0/+3DgqC3k" href="#c_0/+3DgqC3k"></a><span class="cm-keyword">var</span> <span class="cm-variable">names</span> <span class="cm-operator">=</span> [<span class="cm-string">"Sunday"</span>, <span class="cm-string">"Monday"</span>, <span class="cm-string">"Tuesday"</span>, <span class="cm-string">"Wednesday"</span>,
<span class="cm-string">"Thursday"</span>, <span class="cm-string">"Friday"</span>, <span class="cm-string">"Saturday"</span>];
<span class="cm-keyword">function</span> <span class="cm-variable">dayName</span>(<span class="cm-def">number</span>) {
<span class="cm-keyword">return</span> <span class="cm-variable">names</span>[<span class="cm-variable-2">number</span>];
}
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">dayName</span>(<span class="cm-number">1</span>));
<span class="cm-comment">// → Monday</span></pre>
<p><a class=p_ident id="p_lljN2eMCck" href="#p_lljN2eMCck"></a>The <code>dayName</code> function is part
of the module’s interface, but the <code>names</code> variable is not. We
would prefer <em>not</em> to spill it into the global scope.</p>
<p><a class=p_ident id="p_NKmpNxgsFg" href="#p_NKmpNxgsFg"></a>We can do this:</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_cQrjXVzz5t" href="#c_cQrjXVzz5t"></a><span class="cm-keyword">var</span> <span class="cm-variable">dayName</span> <span class="cm-operator">=</span> <span class="cm-keyword">function</span>() {
<span class="cm-keyword">var</span> <span class="cm-def">names</span> <span class="cm-operator">=</span> [<span class="cm-string">"Sunday"</span>, <span class="cm-string">"Monday"</span>, <span class="cm-string">"Tuesday"</span>, <span class="cm-string">"Wednesday"</span>,
<span class="cm-string">"Thursday"</span>, <span class="cm-string">"Friday"</span>, <span class="cm-string">"Saturday"</span>];
<span class="cm-keyword">return</span> <span class="cm-keyword">function</span>(<span class="cm-def">number</span>) {
<span class="cm-keyword">return</span> <span class="cm-variable-2">names</span>[<span class="cm-variable-2">number</span>];
};
}();
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">dayName</span>(<span class="cm-number">3</span>));
<span class="cm-comment">// → Wednesday</span></pre>
<p><a class=p_ident id="p_wFyqiGP0o5" href="#p_wFyqiGP0o5"></a>Now <code>names</code> is a local variable in an
(unnamed) function. This function is created and immediately called,
and its return value (the actual <code>dayName</code> function) is stored in a
variable. We could have pages and pages of code in this function, with
100 local variables, and they would all be internal to our
module—visible to the module itself but not to outside code.</p>
<p><a class=p_ident id="p_XMMYXbTqGr" href="#p_XMMYXbTqGr"></a>We can use a similar pattern to
isolate code from the outside world entirely. The following module logs a
value to the console but does not actually provide any values for
other modules to use:</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_HzELhaatCS" href="#c_HzELhaatCS"></a>(<span class="cm-keyword">function</span>() {
<span class="cm-keyword">function</span> <span class="cm-def">square</span>(<span class="cm-def">x</span>) { <span class="cm-keyword">return</span> <span class="cm-variable-2">x</span> <span class="cm-operator">*</span> <span class="cm-variable-2">x</span>; }
<span class="cm-keyword">var</span> <span class="cm-def">hundred</span> <span class="cm-operator">=</span> <span class="cm-number">100</span>;
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable-2">square</span>(<span class="cm-variable-2">hundred</span>));
})();
<span class="cm-comment">// → 10000</span></pre>
<p><a class=p_ident id="p_NhLZMeErEJ" href="#p_NhLZMeErEJ"></a>This code simply outputs the square of 100,
but in the real world it could be a module that adds a method
to some prototype or sets up a widget on a web page. It is
wrapped in a function to prevent the variables it uses internally from
polluting the global scope.</p>
<p><a class=p_ident id="p_TMPi6xxW7Y" href="#p_TMPi6xxW7Y"></a>Why did we wrap the namespace
function in a pair of parentheses? This has to do with a quirk in
JavaScript’s syntax. If an <em>expression</em> starts with the
keyword <code>function</code>, it is a function expression. However, if a
<em>statement</em> starts with <code>function</code>, it is a function
<em>declaration</em>, which requires a name and, not being an expression,
cannot be called by writing parentheses after it. You can think of the
extra wrapping parentheses as a trick to force the function to be
interpreted as an expression.</p>
<h2><a class=h_ident id="h_tbrMjRcajd" href="#h_tbrMjRcajd"></a>Objects as interfaces</h2>
<p><a class=p_ident id="p_jaxyyZ13ux" href="#p_jaxyyZ13ux"></a>Now imagine that we want to add another function to our
day-of-the-week module, one that goes from a day name to a
number. We can’t simply return the function anymore but must wrap the
two functions in an object.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_j+iqUdoU2O" href="#c_j+iqUdoU2O"></a><span class="cm-keyword">var</span> <span class="cm-variable">weekDay</span> <span class="cm-operator">=</span> <span class="cm-keyword">function</span>() {
<span class="cm-keyword">var</span> <span class="cm-def">names</span> <span class="cm-operator">=</span> [<span class="cm-string">"Sunday"</span>, <span class="cm-string">"Monday"</span>, <span class="cm-string">"Tuesday"</span>, <span class="cm-string">"Wednesday"</span>,
<span class="cm-string">"Thursday"</span>, <span class="cm-string">"Friday"</span>, <span class="cm-string">"Saturday"</span>];
<span class="cm-keyword">return</span> {
<span class="cm-property">name</span>: <span class="cm-keyword">function</span>(<span class="cm-def">number</span>) { <span class="cm-keyword">return</span> <span class="cm-variable-2">names</span>[<span class="cm-variable-2">number</span>]; },
<span class="cm-property">number</span>: <span class="cm-keyword">function</span>(<span class="cm-def">name</span>) { <span class="cm-keyword">return</span> <span class="cm-variable-2">names</span>.<span class="cm-property">indexOf</span>(<span class="cm-variable-2">name</span>); }
};
}();
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">weekDay</span>.<span class="cm-property">name</span>(<span class="cm-variable">weekDay</span>.<span class="cm-property">number</span>(<span class="cm-string">"Sunday"</span>)));
<span class="cm-comment">// → Sunday</span></pre>
<p><a class=p_ident id="p_67L/Eo8MtL" href="#p_67L/Eo8MtL"></a>For bigger modules,
gathering all the <em>exported</em> values into an object at the end of the
function becomes awkward since many of the exported functions are
likely to be big and you’d prefer to write them somewhere else, near
related internal code. A convenient alternative is to declare an
object (conventionally named <code>exports</code>) and add properties to that
whenever we are defining something that needs to be exported. In the
following example, the module function takes its interface object as
an argument, allowing code outside of the function to create it and store
it in a variable. (Outside of a function, <code>this</code> refers to the global
scope object.)</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_qHa2RFvopi" href="#c_qHa2RFvopi"></a>(<span class="cm-keyword">function</span>(<span class="cm-def">exports</span>) {
<span class="cm-keyword">var</span> <span class="cm-def">names</span> <span class="cm-operator">=</span> [<span class="cm-string">"Sunday"</span>, <span class="cm-string">"Monday"</span>, <span class="cm-string">"Tuesday"</span>, <span class="cm-string">"Wednesday"</span>,
<span class="cm-string">"Thursday"</span>, <span class="cm-string">"Friday"</span>, <span class="cm-string">"Saturday"</span>];
<span class="cm-variable-2">exports</span>.<span class="cm-property">name</span> <span class="cm-operator">=</span> <span class="cm-keyword">function</span>(<span class="cm-def">number</span>) {
<span class="cm-keyword">return</span> <span class="cm-variable-2">names</span>[<span class="cm-variable-2">number</span>];
};
<span class="cm-variable-2">exports</span>.<span class="cm-property">number</span> <span class="cm-operator">=</span> <span class="cm-keyword">function</span>(<span class="cm-def">name</span>) {
<span class="cm-keyword">return</span> <span class="cm-variable-2">names</span>.<span class="cm-property">indexOf</span>(<span class="cm-variable-2">name</span>);
};
})(<span class="cm-keyword">this</span>.<span class="cm-property">weekDay</span> <span class="cm-operator">=</span> {});
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">weekDay</span>.<span class="cm-property">name</span>(<span class="cm-variable">weekDay</span>.<span class="cm-property">number</span>(<span class="cm-string">"Saturday"</span>)));
<span class="cm-comment">// → Saturday</span></pre>
<h2><a class=h_ident id="h_ryZfYeSnJy" href="#h_ryZfYeSnJy"></a>Detaching from the global scope</h2>
<p><a class=p_ident id="p_AfCtO+ifwZ" href="#p_AfCtO+ifwZ"></a>The previous pattern is commonly used by JavaScript
modules intended for the browser. The module will claim a single
global variable and wrap its code in a function in order to have its
own private namespace. But this pattern still causes problems if
multiple modules happen to claim the same name or if you want to load
two versions of a module alongside each other.</p>
<p><a class=p_ident id="p_Y2ejGOe+u4" href="#p_Y2ejGOe+u4"></a>With a little plumbing, we
can create a system that allows one module to directly ask for the
interface object of another module, without going through the
global scope. Our goal is a <code>require</code> function that, when given a
module name, will load that module’s file (from disk or the Web,
depending on the platform we are running on) and return the
appropriate interface value.</p>
<p><a class=p_ident id="p_6BOb5Vhxc7" href="#p_6BOb5Vhxc7"></a>This approach solves the problems mentioned previously and has the added
benefit of making your program’s dependencies explicit, making it
harder to accidentally make use of some module without stating that
you need it.</p>
<p><a class=p_ident id="p_qsfTCs+Kiu" href="#p_qsfTCs+Kiu"></a>For <code>require</code> we need two
things. First, we want a function <code>readFile</code>, which returns the
content of a given file as a string. (A single such function is not
present in standard JavaScript, but different JavaScript
environments, such as the browser and Node.js, provide their own ways
of accessing files. For now, let’s just pretend we have this
function.) Second, we need to be able to actually execute this
string as JavaScript code.</p>
<h2 id="eval"><a class=h_ident id="h_oeOkEDaadU" href="#h_oeOkEDaadU"></a>Evaluating data as code</h2>
<p><a class=p_ident id="p_jvij1au4eP" href="#p_jvij1au4eP"></a>There are several ways to take
data (a string of code) and run it as part of the current program.</p>
<p><a class=p_ident id="p_sQ1ASk7W7E" href="#p_sQ1ASk7W7E"></a>The most obvious way is the special operator
<code>eval</code>, which will execute a string of code in the <em>current</em> scope.
This is usually a bad idea because it breaks some of the sane
properties that scopes normally have, such as being isolated from the
outside world.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_RanI4EdsYD" href="#c_RanI4EdsYD"></a><span class="cm-keyword">function</span> <span class="cm-variable">evalAndReturnX</span>(<span class="cm-def">code</span>) {
<span class="cm-variable">eval</span>(<span class="cm-variable-2">code</span>);
<span class="cm-keyword">return</span> <span class="cm-variable">x</span>;
}
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">evalAndReturnX</span>(<span class="cm-string">"var x = 2"</span>));
<span class="cm-comment">// → 2</span></pre>
<p><a class=p_ident id="p_dJLBESQexx" href="#p_dJLBESQexx"></a>A better way of interpreting data as code is
to use the <code>Function</code> constructor. This takes two arguments: a string
containing a comma-separated list of argument names and a string
containing the function’s body.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_cZ4LeZbFGl" href="#c_cZ4LeZbFGl"></a><span class="cm-keyword">var</span> <span class="cm-variable">plusOne</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">Function</span>(<span class="cm-string">"n"</span>, <span class="cm-string">"return n + 1;"</span>);
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">plusOne</span>(<span class="cm-number">4</span>));
<span class="cm-comment">// → 5</span></pre>
<p><a class=p_ident id="p_8DGWg5jk7v" href="#p_8DGWg5jk7v"></a>This is precisely what we need for our modules. We can wrap a module’s
code in a function, with that function’s scope becoming our module
scope.</p>
<h2 id="commonjs"><a class=h_ident id="h_v/XE3QWFpP" href="#h_v/XE3QWFpP"></a>Require</h2>
<p><a class=p_ident id="p_hpfd8nPIk6" href="#p_hpfd8nPIk6"></a>The following is a minimal
implementation of <code>require</code>:</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_1+P7EyFe1w" href="#c_1+P7EyFe1w"></a><span class="cm-keyword">function</span> <span class="cm-variable">require</span>(<span class="cm-def">name</span>) {
<span class="cm-keyword">var</span> <span class="cm-def">code</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">Function</span>(<span class="cm-string">"exports"</span>, <span class="cm-variable">readFile</span>(<span class="cm-variable-2">name</span>));
<span class="cm-keyword">var</span> <span class="cm-def">exports</span> <span class="cm-operator">=</span> {};
<span class="cm-variable-2">code</span>(<span class="cm-variable-2">exports</span>);
<span class="cm-keyword">return</span> <span class="cm-variable-2">exports</span>;
}
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">require</span>(<span class="cm-string">"weekDay"</span>).<span class="cm-property">name</span>(<span class="cm-number">1</span>));
<span class="cm-comment">// → Monday</span></pre>
<p><a class=p_ident id="p_JrILpUgcrH" href="#p_JrILpUgcrH"></a>Since the <code>new Function</code> constructor wraps the module
code in a function, we don’t have to write a wrapping namespace
function in the module file itself. And since we make <code>exports</code> an
argument to the module function, the module does not have to declare
it. This removes a lot of clutter from our example module.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_UcVUK3ap0Z" href="#c_UcVUK3ap0Z"></a><span class="cm-keyword">var</span> <span class="cm-variable">names</span> <span class="cm-operator">=</span> [<span class="cm-string">"Sunday"</span>, <span class="cm-string">"Monday"</span>, <span class="cm-string">"Tuesday"</span>, <span class="cm-string">"Wednesday"</span>,
<span class="cm-string">"Thursday"</span>, <span class="cm-string">"Friday"</span>, <span class="cm-string">"Saturday"</span>];
<span class="cm-variable">exports</span>.<span class="cm-property">name</span> <span class="cm-operator">=</span> <span class="cm-keyword">function</span>(<span class="cm-def">number</span>) {
<span class="cm-keyword">return</span> <span class="cm-variable">names</span>[<span class="cm-variable-2">number</span>];
};
<span class="cm-variable">exports</span>.<span class="cm-property">number</span> <span class="cm-operator">=</span> <span class="cm-keyword">function</span>(<span class="cm-def">name</span>) {
<span class="cm-keyword">return</span> <span class="cm-variable">names</span>.<span class="cm-property">indexOf</span>(<span class="cm-variable-2">name</span>);
};</pre>
<p><a class=p_ident id="p_B75dGyOs9V" href="#p_B75dGyOs9V"></a>When using this pattern, a module typically
starts with a few variable declarations that load the modules it
depends on.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_hczzYLixJt" href="#c_hczzYLixJt"></a><span class="cm-keyword">var</span> <span class="cm-variable">weekDay</span> <span class="cm-operator">=</span> <span class="cm-variable">require</span>(<span class="cm-string">"weekDay"</span>);
<span class="cm-keyword">var</span> <span class="cm-variable">today</span> <span class="cm-operator">=</span> <span class="cm-variable">require</span>(<span class="cm-string">"today"</span>);
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">weekDay</span>.<span class="cm-property">name</span>(<span class="cm-variable">today</span>.<span class="cm-property">dayNumber</span>()));</pre>
<p><a class=p_ident id="p_5GfcRhlMLC" href="#p_5GfcRhlMLC"></a>The simplistic implementation of <code>require</code> given previously
has several problems. For one, it will load and run a module every
time it is <code>require</code>d, so if several modules have the same
dependency or a <code>require</code> call is put inside a function that will
be called multiple times, time and energy will be wasted.</p>
<p><a class=p_ident id="p_zLUwyIBMDV" href="#p_zLUwyIBMDV"></a>This can be solved by storing the modules that have already
been loaded in an object and simply returning the existing value when
one is loaded multiple times.</p>
<p><a class=p_ident id="p_Ylx5bX6l+o" href="#p_Ylx5bX6l+o"></a>The second problem is that it is
not possible for a module to directly export a value other than the
<code>exports</code> object, such as a function. For example, a module might want
to export only the constructor of the object type it defines. Right
now, it cannot do that because <code>require</code> always uses the <code>exports</code>
object it creates as the exported value.</p>
<p><a class=p_ident id="p_RwxY5rq2Qj" href="#p_RwxY5rq2Qj"></a>The traditional solution for this is to provide
modules with another variable, <code>module</code>, which is an object that has a
property <code>exports</code>. This property initially points at the empty object
created by <code>require</code> but can be overwritten with another value in
order to export something else.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_cUUt/BCrSf" href="#c_cUUt/BCrSf"></a><span class="cm-keyword">function</span> <span class="cm-variable">require</span>(<span class="cm-def">name</span>) {
<span class="cm-keyword">if</span> (<span class="cm-variable-2">name</span> <span class="cm-keyword">in</span> <span class="cm-variable">require</span>.<span class="cm-property">cache</span>)
<span class="cm-keyword">return</span> <span class="cm-variable">require</span>.<span class="cm-property">cache</span>[<span class="cm-variable-2">name</span>];
<span class="cm-keyword">var</span> <span class="cm-def">code</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">Function</span>(<span class="cm-string">"exports, module"</span>, <span class="cm-variable">readFile</span>(<span class="cm-variable-2">name</span>));
<span class="cm-keyword">var</span> <span class="cm-def">exports</span> <span class="cm-operator">=</span> {}, <span class="cm-keyword">module</span> <span class="cm-operator">=</span> {<span class="cm-property">exports</span>: <span class="cm-variable-2">exports</span>};
<span class="cm-variable-2">code</span>(<span class="cm-variable-2">exports</span>, <span class="cm-keyword">module</span>);
<span class="cm-variable">require</span>.<span class="cm-property">cache</span>[<span class="cm-variable-2">name</span>] <span class="cm-operator">=</span> <span class="cm-keyword">module</span>.<span class="cm-variable-2">exports</span>;
<span class="cm-keyword">return</span> <span class="cm-keyword">module</span>.<span class="cm-variable-2">exports</span>;
}
<span class="cm-variable">require</span>.<span class="cm-property">cache</span> <span class="cm-operator">=</span> <span class="cm-variable">Object</span>.<span class="cm-property">create</span>(<span class="cm-atom">null</span>);</pre>
<p><a class=p_ident id="p_Dv+TulRay7" href="#p_Dv+TulRay7"></a>We now have a module system that uses a single
global variable (<code>require</code>) to allow modules to find and use each
other without going through the global scope.</p>
<p><a class=p_ident id="p_rvZ9T+1c9y" href="#p_rvZ9T+1c9y"></a>This style of module system is called <em>CommonJS modules</em>, after
the pseudo-standard that first specified it. It is built into the
Node.js system. Real implementations do a lot more than the
example I showed. Most importantly, they have a much more intelligent
way of going from a module name to an actual piece of code, allowing
both pathnames relative to the current file and module names that
point directly to locally installed modules.</p>
<h2 id="amd"><a class=h_ident id="h_A4LDSlASUo" href="#h_A4LDSlASUo"></a>Slow-loading modules</h2>
<p><a class=p_ident id="p_isvKkfyGNv" href="#p_isvKkfyGNv"></a>Though it is possible to use the CommonJS module style when
writing JavaScript for the browser, it is somewhat involved. The
reason for this is that reading a file (module) from the Web is a lot
slower than reading it from the hard disk. While a script is running
in the browser, nothing else can happen to the website on which it
runs, for reasons that will become clear in
<a href="14_event.html#timeline">Chapter 14</a>. This means that if every
<code>require</code> call went and fetched something from some faraway web
server, the page would freeze for a painfully long time while loading
its scripts.</p>
<p><a class=p_ident id="p_Ce7X8+/o7v" href="#p_Ce7X8+/o7v"></a>One way to
work around this problem is to run a program like
<a href="http://browserify.org"><em>Browserify</em></a> on your code before you serve it
on a web page. This will look for calls to <code>require</code>, resolve all
dependencies, and gather the needed code into a single big file.
The website itself can simply load this file to get all the modules
it needs.</p>
<p><a class=p_ident id="p_L9zjrOe2Un" href="#p_L9zjrOe2Un"></a>Another solution is to wrap the
code that makes up your module in a function so that the module loader can first load its dependencies in the background and then
call the function, initializing the module, when the dependencies
have been loaded. That is what the Asynchronous Module Definition
(AMD) module system does.</p>
<p><a class=p_ident id="p_69ZNnLLNhP" href="#p_69ZNnLLNhP"></a>Our trivial program with dependencies would look
like this in AMD:</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_+VGbHf95V3" href="#c_+VGbHf95V3"></a><span class="cm-variable">define</span>([<span class="cm-string">"weekDay"</span>, <span class="cm-string">"today"</span>], <span class="cm-keyword">function</span>(<span class="cm-def">weekDay</span>, <span class="cm-def">today</span>) {
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable-2">weekDay</span>.<span class="cm-property">name</span>(<span class="cm-variable-2">today</span>.<span class="cm-property">dayNumber</span>()));
});</pre>
<p><a class=p_ident id="p_/aD387r6Uv" href="#p_/aD387r6Uv"></a>The <code>define</code>
function is central to this approach. It takes first an array of
module names and then a function that takes one argument for each
dependency. It will load the dependencies (if they haven’t already
been loaded) in the background, allowing the page to continue working
while the files are being fetched. Once all dependencies are loaded,
<code>define</code> will call the function it was given, with the interfaces
of those dependencies as arguments.</p>
<p><a class=p_ident id="p_w7/Slpc0XV" href="#p_w7/Slpc0XV"></a>The modules that are loaded
this way must themselves contain a call to <code>define</code>. The value used as
their interface is whatever was returned by the function passed to
<code>define</code>. Here is the <code>weekDay</code> module again:</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_cye5TZvdJH" href="#c_cye5TZvdJH"></a><span class="cm-variable">define</span>([], <span class="cm-keyword">function</span>() {
<span class="cm-keyword">var</span> <span class="cm-def">names</span> <span class="cm-operator">=</span> [<span class="cm-string">"Sunday"</span>, <span class="cm-string">"Monday"</span>, <span class="cm-string">"Tuesday"</span>, <span class="cm-string">"Wednesday"</span>,
<span class="cm-string">"Thursday"</span>, <span class="cm-string">"Friday"</span>, <span class="cm-string">"Saturday"</span>];
<span class="cm-keyword">return</span> {
<span class="cm-property">name</span>: <span class="cm-keyword">function</span>(<span class="cm-def">number</span>) { <span class="cm-keyword">return</span> <span class="cm-variable-2">names</span>[<span class="cm-variable-2">number</span>]; },
<span class="cm-property">number</span>: <span class="cm-keyword">function</span>(<span class="cm-def">name</span>) { <span class="cm-keyword">return</span> <span class="cm-variable-2">names</span>.<span class="cm-property">indexOf</span>(<span class="cm-variable-2">name</span>); }
};
});</pre>
<p><a class=p_ident id="p_GARnQl+u0i" href="#p_GARnQl+u0i"></a>To be
able to show a minimal implementation of <code>define</code>, we will pretend we
have a <code>backgroundReadFile</code> function that takes a filename and a
function and calls the function with the content of the file as
soon as it has finished loading it. (<a href="17_http.html#getURL">Chapter
17</a> will explain how to write that function.)</p>
<p><a class=p_ident id="p_xNPCNpRiIX" href="#p_xNPCNpRiIX"></a>For the purpose of keeping track of modules while they are being
loaded, the implementation of <code>define</code> will use objects that describe
the state of modules, telling us whether they are available yet and
providing their interface when they are.</p>
<p><a class=p_ident id="p_/Unllb03Bv" href="#p_/Unllb03Bv"></a>The <code>getModule</code> function, when given a name, will return such an
object and ensure that the module is scheduled to be loaded. It uses
a cache object to avoid loading the same module twice.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_hSHaK3C/lo" href="#c_hSHaK3C/lo"></a><span class="cm-keyword">var</span> <span class="cm-variable">defineCache</span> <span class="cm-operator">=</span> <span class="cm-variable">Object</span>.<span class="cm-property">create</span>(<span class="cm-atom">null</span>);
<span class="cm-keyword">var</span> <span class="cm-variable">currentMod</span> <span class="cm-operator">=</span> <span class="cm-atom">null</span>;
<span class="cm-keyword">function</span> <span class="cm-variable">getModule</span>(<span class="cm-def">name</span>) {
<span class="cm-keyword">if</span> (<span class="cm-variable-2">name</span> <span class="cm-keyword">in</span> <span class="cm-variable">defineCache</span>)
<span class="cm-keyword">return</span> <span class="cm-variable">defineCache</span>[<span class="cm-variable-2">name</span>];
<span class="cm-keyword">var</span> <span class="cm-keyword">module</span> <span class="cm-operator">=</span> {<span class="cm-property">exports</span>: <span class="cm-atom">null</span>,
<span class="cm-property">loaded</span>: <span class="cm-atom">false</span>,
<span class="cm-property">onLoad</span>: []};
<span class="cm-variable">defineCache</span>[<span class="cm-variable-2">name</span>] <span class="cm-operator">=</span> <span class="cm-keyword">module</span>;
<span class="cm-variable">backgroundReadFile</span>(<span class="cm-variable-2">name</span>, <span class="cm-keyword">function</span>(<span class="cm-def">code</span>) {
<span class="cm-variable">currentMod</span> <span class="cm-operator">=</span> <span class="cm-keyword">module</span>;
<span class="cm-keyword">new</span> <span class="cm-variable">Function</span>(<span class="cm-string">""</span>, <span class="cm-variable-2">code</span>)();
});
<span class="cm-keyword">return</span> <span class="cm-keyword">module</span>;
}</pre>
<p><a class=p_ident id="p_r9NqByjA7c" href="#p_r9NqByjA7c"></a>We assume the loaded file also contains a
(single) call to <code>define</code>. The <code>currentMod</code> variable is used to tell
this call about the module object that is currently being loaded so
that it can update this object when it finishes loading. We will come
back to this mechanism in a moment.</p>
<p><a class=p_ident id="p_lX37OjlA5W" href="#p_lX37OjlA5W"></a>The <code>define</code> function itself uses
<code>getModule</code> to fetch or create the module objects for the current
module’s dependencies. Its task is to schedule the <code>moduleFunction</code>
(the function that contains the module’s actual code) to be run
whenever those dependencies are loaded. For this purpose, it defines a
function <code>whenDepsLoaded</code> that is added to the <code>onLoad</code> array of all
dependencies that are not yet loaded. This function immediately
returns if there are still unloaded dependencies, so it will do
actual work only once, when the last dependency has finished loading. It is
also called immediately, from <code>define</code> itself, in case there are no
dependencies that need to be loaded.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_1c60YXnLU3" href="#c_1c60YXnLU3"></a><span class="cm-keyword">function</span> <span class="cm-variable">define</span>(<span class="cm-def">depNames</span>, <span class="cm-def">moduleFunction</span>) {
<span class="cm-keyword">var</span> <span class="cm-def">myMod</span> <span class="cm-operator">=</span> <span class="cm-variable">currentMod</span>;
<span class="cm-keyword">var</span> <span class="cm-def">deps</span> <span class="cm-operator">=</span> <span class="cm-variable-2">depNames</span>.<span class="cm-property">map</span>(<span class="cm-variable">getModule</span>);
<span class="cm-variable-2">deps</span>.<span class="cm-property">forEach</span>(<span class="cm-keyword">function</span>(<span class="cm-def">mod</span>) {
<span class="cm-keyword">if</span> (<span class="cm-operator">!</span><span class="cm-variable-2">mod</span>.<span class="cm-property">loaded</span>)
<span class="cm-variable-2">mod</span>.<span class="cm-property">onLoad</span>.<span class="cm-property">push</span>(<span class="cm-variable">whenDepsLoaded</span>);
});
<span class="cm-keyword">function</span> <span class="cm-def">whenDepsLoaded</span>() {
<span class="cm-keyword">if</span> (<span class="cm-operator">!</span><span class="cm-variable-2">deps</span>.<span class="cm-property">every</span>(<span class="cm-keyword">function</span>(<span class="cm-def">m</span>) { <span class="cm-keyword">return</span> <span class="cm-variable-2">m</span>.<span class="cm-property">loaded</span>; }))
<span class="cm-keyword">return</span>;
<span class="cm-keyword">var</span> <span class="cm-def">args</span> <span class="cm-operator">=</span> <span class="cm-variable-2">deps</span>.<span class="cm-property">map</span>(<span class="cm-keyword">function</span>(<span class="cm-def">m</span>) { <span class="cm-keyword">return</span> <span class="cm-variable-2">m</span>.<span class="cm-property">exports</span>; });
<span class="cm-keyword">var</span> <span class="cm-def">exports</span> <span class="cm-operator">=</span> <span class="cm-variable-2">moduleFunction</span>.<span class="cm-property">apply</span>(<span class="cm-atom">null</span>, <span class="cm-variable-2">args</span>);
<span class="cm-keyword">if</span> (<span class="cm-variable-2">myMod</span>) {
<span class="cm-variable-2">myMod</span>.<span class="cm-property">exports</span> <span class="cm-operator">=</span> <span class="cm-variable-2">exports</span>;
<span class="cm-variable-2">myMod</span>.<span class="cm-property">loaded</span> <span class="cm-operator">=</span> <span class="cm-atom">true</span>;
<span class="cm-variable-2">myMod</span>.<span class="cm-property">onLoad</span>.<span class="cm-property">forEach</span>(<span class="cm-keyword">function</span>(<span class="cm-def">f</span>) { <span class="cm-variable-2">f</span>(); });
}
}
<span class="cm-variable-2">whenDepsLoaded</span>();
}</pre>
<p><a class=p_ident id="p_T+RexzI7A0" href="#p_T+RexzI7A0"></a>When all dependencies are available,
<code>whenDepsLoaded</code> calls the function that holds the module, giving it
the dependencies’ interfaces as arguments.</p>
<p><a class=p_ident id="p_8Neb8ba81Q" href="#p_8Neb8ba81Q"></a>The first thing <code>define</code> does is store the value that <code>currentMod</code> had
when it was called in a variable <code>myMod</code>. Remember that <code>getModule</code>,
just before evaluating the code for a module, stored the corresponding
module object in <code>currentMod</code>. This allows <code>whenDepsLoaded</code> to store
the return value of the module function in that module’s <code>exports</code>
property, set the module’s <code>loaded</code> property to true, and call all the
functions that are waiting for the module to load.</p>
<p><a class=p_ident id="p_KBR+VgwyVz" href="#p_KBR+VgwyVz"></a>This code is a lot harder to follow than
the <code>require</code> function. Its execution does not follow a simple,
predictable path. Instead, multiple operations are set up to happen at
some unspecified time in the future, which obscures the way the
code executes.</p>
<p><a class=p_ident id="p_uewjoUxlIw" href="#p_uewjoUxlIw"></a>A real AMD implementation is, again, quite a lot more clever about
resolving module names to actual URLs and generally more robust than
the one shown previously. The <em>RequireJS</em> (<a href="http://requirejs.org"><em>requirejs.org</em></a>) project provides
a popular implementation of this style of module loader.</p>
<h2><a class=h_ident id="h_4266RdeHYR" href="#h_4266RdeHYR"></a>Interface design</h2>
<p><a class=p_ident id="p_IUZ7uTWwwd" href="#p_IUZ7uTWwwd"></a>Designing interfaces for modules and object
types is one of the subtler aspects of programming. Any nontrivial
piece of functionality can be modeled in various ways. Finding a way that
works well requires insight and foresight.</p>
<p><a class=p_ident id="p_KweUtWCb7f" href="#p_KweUtWCb7f"></a>The best way to learn the value of good interface design is to use
lots of interfaces—some good, some bad. Experience will teach
you what works and what doesn’t. Never assume that a painful interface
is “just the way it is”. Fix it, or wrap it in a new interface that
works better for you.</p>
<h3><a class=h_ident id="h_D19q+FXBVd" href="#h_D19q+FXBVd"></a>Predictability</h3>
<p><a class=p_ident id="p_2adqTW0fxP" href="#p_2adqTW0fxP"></a>If programmers
can predict the way your interface works, they (or you) won’t get
sidetracked as often by the need to look up how to use it. Thus, try
to follow conventions. When there is another module or part of the
standard JavaScript environment that does something similar to what
you are implementing, it might be a good idea to make your interface
resemble the existing interface. That way, it’ll feel familiar to
people who know the existing interface.</p>
<p><a class=p_ident id="p_6l6v5cakoT" href="#p_6l6v5cakoT"></a>Another area where predictability is important is the
actual <em>behavior</em> of your code. It can be tempting to make an
unnecessarily clever interface with the justification that it’s more
convenient to use. For example, you could accept all kinds of
different types and combinations of arguments and do the “right
thing” for all of them. Or you could provide dozens of specialized
convenience functions that provide slightly different flavors of your
module’s functionality. These might make code that builds on your
interface slightly shorter, but they will also make it much harder for
people to build a clear mental model of the module’s behavior.</p>
<h3><a class=h_ident id="h_+NeFt8aXxf" href="#h_+NeFt8aXxf"></a>Composability</h3>
<p><a class=p_ident id="p_9Nt/796F0G" href="#p_9Nt/796F0G"></a>In your interfaces, try to use the simplest data structures possible and make functions do a single, clear thing.
Whenever practical, make them pure functions (see
<a href="03_functions.html#pure">Chapter 3</a>).</p>
<p><a class=p_ident id="p_qicKwwcIoO" href="#p_qicKwwcIoO"></a>For example, it is not uncommon for modules to
provide their own array-like collection objects, with their own
interface for counting and extracting elements. Such objects won’t
have <code>map</code> or <code>forEach</code> methods, and any existing function that
expects a real array won’t be able to work with them. This is an
example of poor <em>composability</em>—the module cannot be easily composed
with other code.</p>
<p><a class=p_ident id="p_XJefBK7ici" href="#p_XJefBK7ici"></a>One example would be a
module for spell-checking text, which we might need when we want to
write a text editor. The spell-checker could be made to operate
directly on whichever complicated data structures the editor uses
and directly call internal functions in the editor to have the user
choose between spelling suggestions. If we go that way, the module
cannot be used with any other programs. On the other hand, if we
define the spell-checking interface so that you can pass it a simple
string and it will return the position in the string where it found a
possible misspelling, along with an array of suggested corrections,
then we have an interface that could also be composed with other
systems because strings and arrays are always available in
JavaScript.</p>
<h3><a class=h_ident id="h_vguoN2JlWc" href="#h_vguoN2JlWc"></a>Layered interfaces</h3>
<p><a class=p_ident id="p_gVRzuTdJxo" href="#p_gVRzuTdJxo"></a>When designing an interface for a complex piece of
functionality—sending email, for example—you often run into a dilemma.
On the one hand, you do not want to overload the user of your
interface with details. They shouldn’t have to study your interface
for 20 minutes before they can send an email. On the other hand, you
do not want to hide all the details either—when people need to do
complicated things with your module, they should be able to.</p>
<p><a class=p_ident id="p_UAqdlcM0M6" href="#p_UAqdlcM0M6"></a>Often the solution is to provide two interfaces: a detailed
<em>low-level</em> one for complex situations and a simple <em>high-level</em> one
for routine use. The second can usually be built easily using the
tools provided by the first. In the email module, the high-level
interface could just be a function that takes a message, a sender
address, and a receiver address and then sends the email. The low-level
interface would allow full control over email headers, attachments,
HTML mail, and so on.</p>
<h2><a class=h_ident id="h_ErccPg/l98" href="#h_ErccPg/l98"></a>Summary</h2>
<p><a class=p_ident id="p_hGwRhRocwV" href="#p_hGwRhRocwV"></a>Modules provide structure to bigger programs by separating the code
into different files and namespaces. Giving these modules well-defined
interfaces makes them easier to use and reuse
and makes it possible to continue using them as the module
itself evolves.</p>
<p><a class=p_ident id="p_G2usOklg33" href="#p_G2usOklg33"></a>Though the JavaScript language is characteristically unhelpful
when it comes to modules, the flexible functions and objects it
provides make it possible to define rather nice module systems.
Function scopes can be used as internal namespaces for the module, and
objects can be used to store sets of exported values.</p>
<p><a class=p_ident id="p_0LAk7BPgRr" href="#p_0LAk7BPgRr"></a>There are two popular, well-defined approaches to such modules. One is
called <em>CommonJS Modules</em> and revolves around a <code>require</code> function
that fetches a module by name and returns its interface. The other is
called <em>AMD</em> and uses a <code>define</code> function that takes an array of
module names and a function and, after loading the modules, runs the
function with their interfaces as arguments.</p>
<h2><a class=h_ident id="h_TcUD2vzyMe" href="#h_TcUD2vzyMe"></a>Exercises</h2>
<h3><a class=h_ident id="h_Ft63zbY95i" href="#h_Ft63zbY95i"></a>Month names</h3>
<p><a class=p_ident id="p_dU0pnoSPR9" href="#p_dU0pnoSPR9"></a>Write a
simple module similar to the <code>weekDay</code> module that can convert month
numbers (zero-based, as in the <code>Date</code> type) to names and can convert names back
to numbers. Give it its own namespace since it will need an internal
array of month names, and use plain JavaScript, without any module
loader system.</p>
<pre data-language="javascript" class="snippet cm-s-default"><a class=c_ident id="c_YcMMskAlqo" href="#c_YcMMskAlqo"></a><span class="cm-comment">// Your code here.</span>
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">month</span>.<span class="cm-property">name</span>(<span class="cm-number">2</span>));
<span class="cm-comment">// → March</span>
<span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-variable">month</span>.<span class="cm-property">number</span>(<span class="cm-string">"November"</span>));
<span class="cm-comment">// → 10</span></pre>
<div class=solution><div class=solution-text>
<p><a class=p_ident id="p_N564mECTK6" href="#p_N564mECTK6"></a>This follows the <code>weekDay</code> module almost
exactly. A function expression, called immediately, wraps the variable
that holds the array of names, along with the two functions that must
be exported. The functions are put in an object and returned. The
returned interface object is stored in the <code>month</code> variable.</p>
</div></div>
<h3><a class=h_ident id="h_3j/KaVGNV2" href="#h_3j/KaVGNV2"></a>A return to electronic life</h3>
<p><a class=p_ident id="p_+royQ52RxC" href="#p_+royQ52RxC"></a>Hoping that
<a href="07_elife.html#elife">Chapter 7</a> is still somewhat fresh in your
mind, think back to the system designed in that chapter and come up
with a way to separate the code into modules. To refresh your memory,
these are the functions and types defined in that chapter, in order of
appearance:</p>
<pre>Vector
Grid
directions
directionNames
randomElement
BouncingCritter
elementFromChar
World
charFromElement
Wall
View
WallFollower
dirPlus
LifelikeWorld
Plant
PlantEater
SmartPlantEater
Tiger</pre>
<p><a class=p_ident id="p_qH0Xj8v2nH" href="#p_qH0Xj8v2nH"></a>Don’t exaggerate and create too many modules. A book
that starts a new chapter for every page would probably get on your
nerves, if only because of all the space wasted on titles. Similarly,
having to open 10 files to read a tiny project isn’t helpful. Aim for
three to five modules.</p>
<p><a class=p_ident id="p_fDzWqQqyw8" href="#p_fDzWqQqyw8"></a>You can choose to have some functions become
internal to their module and thus inaccessible to other modules.</p>
<p><a class=p_ident id="p_XYYo0/YDOl" href="#p_XYYo0/YDOl"></a>There is no single correct solution here. Module organization is
largely a matter of taste.</p>
<div class=solution><div class=solution-text>
<p><a class=p_ident id="p_E3iJwXoILn" href="#p_E3iJwXoILn"></a>Here is what I came up with. I’ve put parentheses around internal
functions.</p>
<pre>Module "grid"
Vector
Grid
directions
directionNames
Module "world"
(randomElement)
(elementFromChar)
(charFromElement)
View
World
LifelikeWorld
directions [reexported]
Module "simple_ecosystem"
(randomElement) [duplicated]
(dirPlus)
Wall
BouncingCritter
WallFollower
Module "ecosystem"
Wall [duplicated]
Plant
PlantEater
SmartPlantEater
Tiger</pre>
<p><a class=p_ident id="p_VwnqNlhTuk" href="#p_VwnqNlhTuk"></a>I have reexported the <code>directions</code> array from the
<code>grid</code> module from <code>world</code> so that modules built on that (the
ecosystems) don’t have to know or worry about the existence of the
<code>grid</code> module.</p>
<p><a class=p_ident id="p_2pzeyE24tw" href="#p_2pzeyE24tw"></a>I also duplicated two generic and tiny helper values
(<code>randomElement</code> and <code>Wall</code>) since they are used as internal details
in different contexts and do not belong in the interfaces for these
modules.</p>
</div></div>
<h3><a class=h_ident id="h_E/zWqBFdy8" href="#h_E/zWqBFdy8"></a>Circular dependencies</h3>
<p><a class=p_ident id="p_/LVNV6+2SH" href="#p_/LVNV6+2SH"></a>A
tricky subject in dependency management is circular dependencies,
where module A depends on B, and B also depends on A. Many module
systems simply forbid this. CommonJS modules allow a limited form:
it works as long as the modules do not replace their default <code>exports</code>
object with another value and start accessing each other’s
interface only after they finish loading.</p>
<p><a class=p_ident id="p_BFm3QczrDZ" href="#p_BFm3QczrDZ"></a>Can you think of a way in which support for this feature could be
implemented? Look back to the definition of <code>require</code> and consider
what the function would have to do to allow this.</p>
<div class=solution><div class=solution-text>
<p><a class=p_ident id="p_By5oQNAE2m" href="#p_By5oQNAE2m"></a>The trick
is to add the <code>exports</code> object created for a module to <code>require</code>'s
cache <em>before</em> actually running the module. This means the module
will not yet have had a chance to override <code>module.exports</code>, so we do
not know whether it may want to export some other value. After
loading, the cache object is overridden with <code>module.exports</code>, which
may be a different value.</p>
<p><a class=p_ident id="p_xRLcTfyWjS" href="#p_xRLcTfyWjS"></a>But if in the course of loading the module, a second module is loaded
that asks for the first module, its default <code>exports</code> object, which is likely
still empty at this point, will be in the cache, and the second module
will receive a reference to it. If it doesn’t try to do anything with
the object until the first module has finished loading, things will
work.</p>
</div></div>
<nav>
<a href="09_regexp.html" title="previous chapter">◀</a>
<a href="index.html" title="cover">◆</a>
<a href="11_language.html" title="next chapter">▶</a>
</nav>
</article>