A Modern Introduction to Programming by Marijn Haverbeke
Publishing documents on edocr is a proven way to start demand generation for your products and services. Thousands of professionals and businesses publish marketing (brochures, data sheets, press releases, white papers and case studies), sales (slides, price lists and pro-forma agreements), operations (specifications, operating manuals, installation guides), customer service (user manuals) and financial (annual reports and financial statements) documents making it easier for prospects and customers to find content, helping them to make informed decisions. #SEO #leadgen #content #analytics
info@edocr.com
About edocr
I am an accomplished content marketing professional helping you to build your brand and business. In my current role, I fulfill a multi-faceted solution marketplace including: publishing and sharing your content, embedding a document viewer on your website, improving your content’s search engine optimization, generating leads with gated content and earning money by selling your documents. I gobble up documents, storing them for safekeeping and releasing the text for excellent search engine optimization, lead generation and earned income.
Publishing documents on edocr.com is a proven way to start demand generation for your products and services. Thousands of professionals and businesses publish marketing, sales, operations, customer service and financial documents making it easier for prospects and customers to find content, helping them to make informed decisions.
Get publishing now!
Tag Cloud
Eloquent JavaScript
A Modern Introduction to Programming
Marijn Haverbeke
Copyright © 2014 by Marijn Haverbeke
This work is licensed under a Creative Commons attribution-noncommercial
license (http://creativecommons.org/licenses/by-nc/3.0/). All code in the
book may also be considered licensed under an MIT license (http://
opensource.org/licenses/MIT).
The illustrations are contributed by various artists: Cover by Wasif
Hyder. Computer (introduction) and unicycle people (Chapter 21) by
Max Xiantu. Sea of bits (Chapter 1) and weresquirrel (Chapter 4) by
Margarita Martínez and José Menor. Octopuses (Chapter 2 and 4) by
Jim Tierney. Object with on/off switch (Chapter 6) by Dyle MacGregor.
Regular expression diagrams in Chapter 9 generated with regexper.com
by Jeff Avallone. Game concept for Chapter 15 by Thomas Palef. Pixel
art in Chapter 16 by Antonio Perdomo Pastor.
The second edition of Eloquent JavaScript was made possible by 454
financial backers.
You can buy a print version of this book, with an extra bonus chapter
included, printed by No Starch Press at http://www.amazon.com/gp/product/
1593275846/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=
1593275846&linkCode=as2&tag=marijhaver-20&linkId=VPXXXSRYC5COG5R5.
i
Contents
On programming
. . . . . . . . . . . . . . . . . . . . . . . . . .
2
Why language matters . . . . . . . . . . . . . . . . . . . . . . .
4
What is JavaScript? . . . . . . . . . . . . . . . . . . . . . . . . .
6
Code, and what to do with it
. . . . . . . . . . . . . . . . . . .
8
Overview of this book . . . . . . . . . . . . . . . . . . . . . . . .
9
Typographic conventions . . . . . . . . . . . . . . . . . . . . . .
10
1 Values, Types, and Operators
11
Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
Strings
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
Unary operators . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
Boolean values . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
Undefined values . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
Automatic type conversion . . . . . . . . . . . . . . . . . . . . .
19
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
2 Program Structure
23
Expressions and statements
. . . . . . . . . . . . . . . . . . . .
23
Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
Keywords and reserved words . . . . . . . . . . . . . . . . . . .
26
The environment
. . . . . . . . . . . . . . . . . . . . . . . . . .
27
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
The console.log function . . . . . . . . . . . . . . . . . . . . . .
28
Return values
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
prompt and confirm . . . . . . . . . . . . . . . . . . . . . . . . .
29
Control flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
Conditional execution . . . . . . . . . . . . . . . . . . . . . . . .
30
while and do loops . . . . . . . . . . . . . . . . . . . . . . . . . .
32
Indenting Code
. . . . . . . . . . . . . . . . . . . . . . . . . . .
34
ii
for loops
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
Breaking Out of a Loop
. . . . . . . . . . . . . . . . . . . . . .
36
Updating variables succinctly . . . . . . . . . . . . . . . . . . .
36
Dispatching on a value with switch . . . . . . . . . . . . . . . .
37
Capitalization . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
3 Functions
42
Defining a function . . . . . . . . . . . . . . . . . . . . . . . . .
42
Parameters and scopes . . . . . . . . . . . . . . . . . . . . . . .
43
Nested scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
45
Functions as values . . . . . . . . . . . . . . . . . . . . . . . . .
46
Declaration notation
. . . . . . . . . . . . . . . . . . . . . . . .
47
The call stack . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
Optional Arguments . . . . . . . . . . . . . . . . . . . . . . . . .
49
Closure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
Growing functions . . . . . . . . . . . . . . . . . . . . . . . . . .
55
Functions and side effects
. . . . . . . . . . . . . . . . . . . . .
58
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
4 Data Structures: Objects and Arrays
61
The weresquirrel . . . . . . . . . . . . . . . . . . . . . . . . . . .
61
Data sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
Properties
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
63
Methods
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
65
Mutability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
68
The lycanthrope’s log . . . . . . . . . . . . . . . . . . . . . . . .
69
Computing correlation . . . . . . . . . . . . . . . . . . . . . . .
71
Objects as maps . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
The final analysis . . . . . . . . . . . . . . . . . . . . . . . . . .
74
Further arrayology . . . . . . . . . . . . . . . . . . . . . . . . . .
76
Strings and their properties
. . . . . . . . . . . . . . . . . . . .
78
iii
The arguments object . . . . . . . . . . . . . . . . . . . . . . . .
79
The Math object . . . . . . . . . . . . . . . . . . . . . . . . . . .
80
The global object . . . . . . . . . . . . . . . . . . . . . . . . . .
82
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
82
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
83
5 Higher-Order Functions
86
Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
87
Abstracting array traversal . . . . . . . . . . . . . . . . . . . . .
88
Higher-order functions
. . . . . . . . . . . . . . . . . . . . . . .
90
Passing along arguments . . . . . . . . . . . . . . . . . . . . . .
91
JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
Filtering an array . . . . . . . . . . . . . . . . . . . . . . . . . .
94
Transforming with map . . . . . . . . . . . . . . . . . . . . . . .
95
Summarizing with reduce . . . . . . . . . . . . . . . . . . . . . .
95
Composability . . . . . . . . . . . . . . . . . . . . . . . . . . . .
96
The cost
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
Great-great-great-great-… . . . . . . . . . . . . . . . . . . . . . .
99
Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6 The Secret Life of Objects
105
History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Methods
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
Prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Overriding derived properties
. . . . . . . . . . . . . . . . . . . 110
Prototype interference
. . . . . . . . . . . . . . . . . . . . . . . 112
Prototype-less objects . . . . . . . . . . . . . . . . . . . . . . . . 114
Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Laying out a table . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Getters and setters
. . . . . . . . . . . . . . . . . . . . . . . . . 121
Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
The instanceof operator . . . . . . . . . . . . . . . . . . . . . . . 124
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
iv
7 Project: Electronic Life
128
Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Representing space
. . . . . . . . . . . . . . . . . . . . . . . . . 129
A critter’s programming interface . . . . . . . . . . . . . . . . . 131
The world object
. . . . . . . . . . . . . . . . . . . . . . . . . . 132
this and its scope . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Animating life . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
It moves
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
More life forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
A more lifelike simulation
. . . . . . . . . . . . . . . . . . . . . 141
Action handlers
. . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Populating the new world
. . . . . . . . . . . . . . . . . . . . . 144
Bringing it to life
. . . . . . . . . . . . . . . . . . . . . . . . . . 145
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
8 Bugs and Error Handling
149
Programmer mistakes . . . . . . . . . . . . . . . . . . . . . . . . 149
Strict mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Error propagation . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Cleaning up after exceptions . . . . . . . . . . . . . . . . . . . . 157
Selective catching . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Assertions
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
9 Regular Expressions
164
Creating a regular expression . . . . . . . . . . . . . . . . . . . 164
Testing for matches . . . . . . . . . . . . . . . . . . . . . . . . . 165
Matching a set of characters . . . . . . . . . . . . . . . . . . . . 165
Repeating parts of a pattern . . . . . . . . . . . . . . . . . . . . 167
Grouping subexpressions . . . . . . . . . . . . . . . . . . . . . . 168
Matches and groups . . . . . . . . . . . . . . . . . . . . . . . . . 168
The date type . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
Word and string boundaries . . . . . . . . . . . . . . . . . . . . 171
v
Choice patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
The mechanics of matching
. . . . . . . . . . . . . . . . . . . . 172
Backtracking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
The replace method . . . . . . . . . . . . . . . . . . . . . . . . . 176
Greed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Dynamically creating RegExp objects
. . . . . . . . . . . . . . 179
The search method . . . . . . . . . . . . . . . . . . . . . . . . . 180
The lastIndex property . . . . . . . . . . . . . . . . . . . . . . . 180
Parsing an INI file . . . . . . . . . . . . . . . . . . . . . . . . . . 182
International characters . . . . . . . . . . . . . . . . . . . . . . . 184
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
10 Modules
188
Why modules help . . . . . . . . . . . . . . . . . . . . . . . . . . 188
Using functions as namespaces . . . . . . . . . . . . . . . . . . . 191
Objects as interfaces
. . . . . . . . . . . . . . . . . . . . . . . . 192
Detaching from the global scope . . . . . . . . . . . . . . . . . . 193
Evaluating data as code
. . . . . . . . . . . . . . . . . . . . . . 194
Require . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Slow-loading modules . . . . . . . . . . . . . . . . . . . . . . . . 197
Interface design . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
11 Project: A Programming Language
205
Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
The evaluator
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Special forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
The environment
. . . . . . . . . . . . . . . . . . . . . . . . . . 213
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
Cheating . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
12 JavaScript and the Browser
220
Networks and the Internet . . . . . . . . . . . . . . . . . . . . . 220
vi
The Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
HTML and JavaScript
. . . . . . . . . . . . . . . . . . . . . . . 225
In the sandbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Compatibility and the browser wars
. . . . . . . . . . . . . . . 227
13 The Document Object Model
229
Document structure . . . . . . . . . . . . . . . . . . . . . . . . . 229
Trees
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
The standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
Moving through the tree . . . . . . . . . . . . . . . . . . . . . . 233
Finding elements
. . . . . . . . . . . . . . . . . . . . . . . . . . 234
Changing the document
. . . . . . . . . . . . . . . . . . . . . . 235
Creating nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
Attributes
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
Layout
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
Styling
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
Cascading styles . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Query selectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Positioning and animating . . . . . . . . . . . . . . . . . . . . . 246
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
14 Handling Events
252
Event handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
Events and DOM nodes
. . . . . . . . . . . . . . . . . . . . . . 253
Event objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
Default actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
Key events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
Mouse clicks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Mouse motion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
Scroll events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
Focus events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
Load event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
Script execution timeline . . . . . . . . . . . . . . . . . . . . . . 266
Setting timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
vii
Debouncing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
15 Project: A Platform Game
272
The game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
The technology
. . . . . . . . . . . . . . . . . . . . . . . . . . . 273
Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
Reading a level . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Actors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
Encapsulation as a burden . . . . . . . . . . . . . . . . . . . . . 279
Drawing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
Motion and collision . . . . . . . . . . . . . . . . . . . . . . . . . 285
Actors and actions . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Tracking keys
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Running the game . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
16 Drawing on Canvas
297
SVG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
The canvas element . . . . . . . . . . . . . . . . . . . . . . . . . 298
Filling and stroking . . . . . . . . . . . . . . . . . . . . . . . . . 300
Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
Curves
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
Drawing a pie chart . . . . . . . . . . . . . . . . . . . . . . . . . 306
Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
Images
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
Transformation
. . . . . . . . . . . . . . . . . . . . . . . . . . . 310
Storing and clearing transformations . . . . . . . . . . . . . . . 313
Back to the game . . . . . . . . . . . . . . . . . . . . . . . . . . 314
Choosing a graphics interface . . . . . . . . . . . . . . . . . . . 320
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
17 HTTP
324
The protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Browsers and HTTP . . . . . . . . . . . . . . . . . . . . . . . . 326
viii
XMLHttpRequest . . . . . . . . . . . . . . . . . . . . . . . . . . 328
Sending a request . . . . . . . . . . . . . . . . . . . . . . . . . . 328
Asynchronous Requests . . . . . . . . . . . . . . . . . . . . . . . 330
Fetching XML Data . . . . . . . . . . . . . . . . . . . . . . . . . 330
HTTP sandboxing . . . . . . . . . . . . . . . . . . . . . . . . . . 331
Abstracting requests
. . . . . . . . . . . . . . . . . . . . . . . . 332
Promises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
Appreciating HTTP . . . . . . . . . . . . . . . . . . . . . . . . . 338
Security and HTTPS . . . . . . . . . . . . . . . . . . . . . . . . 338
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
18 Forms and Form Fields
342
Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
Focus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
Disabled fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
The form as a whole
. . . . . . . . . . . . . . . . . . . . . . . . 345
Text fields
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Checkboxes and radio buttons . . . . . . . . . . . . . . . . . . . 348
Select fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
File fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Storing data client-side . . . . . . . . . . . . . . . . . . . . . . . 353
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
19 Project: A Paint Program
359
Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
Building the DOM . . . . . . . . . . . . . . . . . . . . . . . . . 360
The foundation
. . . . . . . . . . . . . . . . . . . . . . . . . . . 361
Tool selection
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Color and brush size
. . . . . . . . . . . . . . . . . . . . . . . . 365
Saving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
Loading image files . . . . . . . . . . . . . . . . . . . . . . . . . 368
Finishing up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
20 Node.js
376
ix
Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
Asynchronicity . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
The node command . . . . . . . . . . . . . . . . . . . . . . . . . 378
Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
Installing with NPM . . . . . . . . . . . . . . . . . . . . . . . . 381
The file system module . . . . . . . . . . . . . . . . . . . . . . . 382
The HTTP module . . . . . . . . . . . . . . . . . . . . . . . . . 384
Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
A simple file server
. . . . . . . . . . . . . . . . . . . . . . . . . 388
Error handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
21 Project: Skill-Sharing Website
399
Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
Long polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
HTTP interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
The server
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
The client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
Program Structure
. . . . . . . . . . . . . . . . . . . . . . . . . 424
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
Data Structures: Objects and Arrays . . . . . . . . . . . . . . . 426
Higher-Order Functions . . . . . . . . . . . . . . . . . . . . . . . 428
The Secret Life of Objects . . . . . . . . . . . . . . . . . . . . . 429
Project: Electronic Life . . . . . . . . . . . . . . . . . . . . . . . 430
Bugs and Error Handling . . . . . . . . . . . . . . . . . . . . . . 432
Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . 432
Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
Project: A Programming Language . . . . . . . . . . . . . . . . 435
The Document Object Model
. . . . . . . . . . . . . . . . . . . 436
Handling Events . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
Project: A Platform Game . . . . . . . . . . . . . . . . . . . . . 438
Drawing on Canvas . . . . . . . . . . . . . . . . . . . . . . . . . 439
HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Forms and Form Fields . . . . . . . . . . . . . . . . . . . . . . . 442
Project: A Paint Program . . . . . . . . . . . . . . . . . . . . . 444
x
Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
Project: Skill-Sharing Website . . . . . . . . . . . . . . . . . . . 448
xi
Introduction
This is a book about getting computers to do what you want them to
do. Computers are about as common as screwdrivers today, but they
contain a lot more hidden complexity and thus are harder to operate and
understand. To many, they remain alien, slightly threatening things.
We’ve found two effective ways of bridging the communication gap be-
tween us, squishy biological organisms with a talent for social and spatial
reasoning, and computers, unfeeling manipulators of meaningless data.
The first is to appeal to our sense of the physical world and build in-
terfaces that mimic that world and allow us to manipulate shapes on a
screen with our fingers. This works very well for casual machine inter-
action.
But we have not yet found a good way to use the point-and-click ap-
proach to communicate things to the computer that the designer of the
interface did not anticipate. For open-ended interfaces, such as instruct-
ing the computer to perform arbitrary tasks, we’ve had more luck with
an approach that makes use of our talent for language: teaching the
machine a language.
Human languages allow words and phrases to be combined in many
ways, which allows us to say many different things. Computer languages,
though typically less grammatically flexible, follow a similar principle.
1
Casual computing has become much more widespread in the past 20
years, and language-based interfaces, which once were the default way
in which people interacted with computers, have largely been replaced
with graphical interfaces. But they are still there, if you know where
to look. One such language, JavaScript, is built into almost every web
browser and is thus available on just about every consumer device.
This book intends to make you familiar enough with this language to
be able to make a computer do what you want.
On programming
I do not enlighten those who are not eager to learn, nor arouse
those who are not anxious to give an explanation themselves.
If I have presented one corner of the square and they cannot
come back to me with the other three, I should not go over
the points again.
—Confucius
Besides explaining JavaScript, I also will introduce the basic principles
of programming. Programming, it turns out, is hard. The fundamental
rules are typically simple and clear. But programs built on top of these
rules tend to become complex enough to introduce their own rules and
complexity. You’re building your own maze, in a way, and you might
just get lost in it.
There will be times when reading this book feels terribly frustrating.
If you are new to programming, there will be a lot of new material to
digest. Much of this material will then be combined in ways that require
you to make additional connections.
It is up to you to make the necessary effort. When you are struggling
to follow the book, do not jump to any conclusions about your own
capabilities. You are fine—you just need to keep at it. Take a break,
reread some material, and always make sure you read and understand the
example programs and exercises. Learning is hard work, but everything
you learn is yours and will make subsequent learning easier.
The computer programmer is a creator of universes for which
he [sic] alone is responsible. Universes of virtually unlimited
2
complexity can be created in the form of computer programs.
—Joseph Weizenbaum, Computer Power and Human Reason
A program is many things. It is a piece of text typed by a programmer,
it is the directing force that makes the computer do what it does, it is
data in the computer’s memory, yet it controls the actions performed on
this same memory. Analogies that try to compare programs to objects
we are familiar with tend to fall short. A superficially fitting one is that
of a machine—lots of separate parts tend to be involved, and to make
the whole thing tick, we have to consider the ways in which these parts
interconnect and contribute to the operation of the whole.
A computer is a machine built to act as a host for these immaterial
machines. Computers themselves can do only stupidly straightforward
things. The reason they are so useful is that they do these things at an
incredibly high speed. A program can ingeniously combine an enormous
number of these simple actions in order to do very complicated things.
To some of us, writing computer programs is a fascinating game. A
program is a building of thought. It is costless to build, it is weightless,
and it grows easily under our typing hands.
But without care, a program’s size and complexity will grow out of
control, confusing even the person who created it. Keeping programs
under control is the main problem of programming. When a program
works, it is beautiful. The art of programming is the skill of controlling
complexity. The great program is subdued—made simple in its com-
plexity.
Many programmers believe that this complexity is best managed by
using only a small set of well-understood techniques in their programs.
They have composed strict rules (“best practices”) prescribing the form
programs should have, and the more zealous among them will consider
those who go outside of this safe little zone to be bad programmers.
What hostility to the richness of programming—to try to reduce it
to something straightforward and predictable, to place a taboo on all
the weird and beautiful programs! The landscape of programming tech-
niques is enormous, fascinating in its diversity, and still largely unex-
plored. It is certainly dangerous going, luring the inexperienced pro-
grammer into all kinds of confusion, but that only means you should
proceed with caution and keep your wits about you. As you learn there
3
will always be new challenges and new territory to explore. Program-
mers who refuse to keep exploring will stagnate, forget their joy, and get
bored with their craft.
Why language matters
In the beginning, at the birth of computing, there were no programming
languages. Programs looked something like this:
00110001 00000000 00000000
00110001 00000001 00000001
00110011 00000001 00000010
01010001 00001011 00000010
00100010 00000010 00001000
01000011 00000001 00000000
01000001 00000001 00000001
00010000 00000010 00000000
01100010 00000000 00000000
That is a program to add the numbers from 1 to 10 together and print
out the result: 1 + 2 + ... + 10 = 55.
It could run on a simple, hypo-
thetical machine. To program early computers, it was necessary to set
large arrays of switches in the right position or punch holes in strips of
cardboard and feed them to the computer. You can probably imagine
how tedious and error-prone this procedure was. Even writing simple
programs required much cleverness and discipline. Complex ones were
nearly inconceivable.
Of course, manually entering these arcane patterns of bits (the ones
and zeros) did give the programmer a profound sense of being a mighty
wizard. And that has to be worth something in terms of job satisfaction.
Each line of the previous program contains a single instruction. It
could be written in English like this:
1. Store the number 0 in memory location 0.
2. Store the number 1 in memory location 1.
3. Store the value of memory location 1 in memory location 2.
4. Subtract the number 11 from the value in memory location 2.
5. If the value in memory location 2 is the number 0,
continue with instruction 9.
4
6. Add the value of memory location 1 to memory location 0.
7. Add the number 1 to the value of memory location 1.
8. Continue with instruction 3.
9. Output the value of memory location 0.
Although that is already more readable than the soup of bits, it is still
rather unpleasant. It might help to use names instead of numbers for
the instructions and memory locations.
Set "total" to 0.
Set "count" to 1.
[loop]
Set "compare" to "count".
Subtract 11 from "compare ".
If "compare" is zero , continue at [end].
Add "count" to "total".
Add 1 to "count".
Continue at [loop].
[end]
Output "total".
Can you see how the program works at this point? The first two lines
give two memory locations their starting values: total will be used to
build up the result of the computation, and count will keep track of the
number that we are currently looking at. The lines using compare are
probably the weirdest ones. The program wants to see whether count
is equal to 11 in order to decide whether it can stop running. Because
our hypothetical machine is rather primitive, it can only test whether
a number is zero and make a decision (or jump) based on that. So it
uses the memory location labeled compare to compute the value of count
- 11 and makes a decision based on that value. The next two lines add
the value of count to the result and increment count by 1 every time the
program has decided that count is not 11 yet.
Here is the same program in JavaScript:
var total = 0, count = 1;
while (count <= 10) {
total += count;
count += 1;
}
console.log(total);
5
// ! 55
This version gives us a few more improvements. Most importantly, there
is no need to specify the way we want the program to jump back and forth
anymore. The while language construct takes care of that. It continues
executing the block (wrapped in braces) below it as long as the condition
it was given holds. That condition is count <= 10, which means “count is
less than or equal to 10”. We no longer have to create a temporary value
and compare that to zero, which was an uninteresting detail. Part of the
power of programming languages is that they take care of uninteresting
details for us.
At the end of the program, after the while construct has finished, the
console.log operation is applied to the result in order to write it as output.
Finally, here is what the program could look like if we happened to
have the convenient operations range and sum available, which respectively
create a collection of numbers within a range and compute the sum of a
collection of numbers:
console.log(sum(range(1, 10)));
// ! 55
The moral of this story is that the same program can be expressed in
long and short, unreadable and readable ways. The first version of the
program was extremely obscure, whereas this last one is almost English:
log the sum of the range of numbers from 1 to 10. (We will see in later
chapters how to build operations like sum and range.)
A good programming language helps the programmer by allowing them
to talk about the actions that the computer has to perform on a higher
level. It helps omit uninteresting details, provides convenient building
blocks (such as while and console.log), allows you to define your own
building blocks (such as sum and range), and makes those blocks easy to
compose.
What is JavaScript?
JavaScript was introduced in 1995 as a way to add programs to web pages
in the Netscape Navigator browser. The language has since been adopted
by all other major graphical web browsers. It has made modern web
6
applications possible—applications with which you can interact directly,
without doing a page reload for every action. But it is also used in
more traditional websites to provide various forms of interactivity and
cleverness.
It is important to note that JavaScript has almost nothing to do
with the programming language named Java. The similar name was in-
spired by marketing considerations, rather than good judgment. When
JavaScript was being introduced, the Java language was being heavily
marketed and was gaining popularity. Someone thought it was a good
idea to try to ride along on this success. Now we are stuck with the
name.
After its adoption outside of Netscape, a standard document was writ-
ten to describe the way the JavaScript language should work to make
sure the various pieces of software that claimed to support JavaScript
were actually talking about the same language. This is called the EC-
MAScript standard, after the Ecma International organization that did
the standardization. In practice, the terms ECMAScript and JavaScript
can be used interchangeably—they are two names for the same language.
There are those who will say terrible things about the JavaScript lan-
guage. Many of these things are true. When I was required to write
something in JavaScript for the first time, I quickly came to despise it.
It would accept almost anything I typed but interpret it in a way that
was completely different from what I meant. This had a lot to do with
the fact that I did not have a clue what I was doing, of course, but there
is a real issue here: JavaScript is ridiculously liberal in what it allows.
The idea behind this design was that it would make programming in
JavaScript easier for beginners. In actuality, it mostly makes finding
problems in your programs harder because the system will not point
them out to you.
This flexibility also has its advantages, though. It leaves space for a
lot of techniques that are impossible in more rigid languages, and as you
will see (for example in Chapter 10) it can be used to overcome some
of JavaScript’s shortcomings. After learning the language properly and
working with it for a while, I have learned to actually like JavaScript.
There have been several versions of JavaScript. ECMAScript version
3 was the widely supported version in the time of JavaScript’s ascent
to dominance, roughly between 2000 and 2010. During this time, work
7
was underway on an ambitious version 4, which planned a number of
radical improvements and extensions to the language. Changing a living,
widely used language in such a radical way turned out to be politically
difficult, and work on the version 4 was abandoned in 2008, leading to
the much less ambitious version 5 coming out in 2009. We’re now at the
point where all major browsers support version 5, which is the language
version that this book will be focusing on. A version 6 is in the process of
being finalized, and some browsers are starting to support new features
from this version.
Web browsers are not the only platforms on which JavaScript is used.
Some databases, such as MongoDB and CouchDB, use JavaScript as
their scripting and query language. Several platforms for desktop and
server programming, most notably the Node.js project (the subject of
Chapter 20) are providing a powerful environment for programming
JavaScript outside of the browser.
Code, and what to do with it
Code is the text that makes up programs. Most chapters in this book
contain quite a lot of it. In my experience, reading code and writing code
are indispensable parts of learning to program, so try to not just glance
over the examples. Read them attentively and understand them. This
may be slow and confusing at first, but I promise that you will quickly
get the hang of it. The same goes for the exercises. Don’t assume you
understand them until you’ve actually written a working solution.
I recommend you try your solutions to exercises in an actual JavaScript
interpreter. That way, you’ll get immediate feedback on whether what
you are doing is working, and, I hope, you’ll be tempted to experiment
and go beyond the exercises.
The easiest way to run the example code in the book, and to ex-
periment with it, is to look it up in the online version of the book at
eloquentjavascript.net. There, you can click any code example to edit
and run it and to see the output it produces. To work on the exercises,
go to eloquentjavascript.net/code, which provides starting code for each
coding exercise and allows you to look at the solutions.
If you want to run the programs defined in this book outside of the
8
book’s sandbox, some care is required. Many examples stand on their
own and should work in any JavaScript environment. But code in later
chapters is mostly written for a specific environment (the browser or
Node.js) and can run only there.
In addition, many chapters define
bigger programs, and the pieces of code that appear in them depend on
each other or on external files. The sandbox on the website provides
links to Zip files containing all of the scripts and data files necessary to
run the code for a given chapter.
Overview of this book
This book contains roughly three parts. The first 11 chapters discuss
the JavaScript language itself. The next eight chapters are about web
browsers and the way JavaScript is used to program them. Finally,
two chapters are devoted to Node.js, another environment to program
JavaScript in.
Throughout the book, there are five project chapters, which describe
larger example programs to give you a taste of real programming. In
order of appearance, we will work through building an artificial life sim-
ulation, a programming language, a platform game, a paint program,
and a dynamic website.
The language part of the book starts with four chapters to introduce
the basic structure of the JavaScript language. They introduce control
structures (such as the while word you saw in this introduction), functions
(writing your own operations), and data structures. After these, you
will be able to write simple programs. Next, Chapters 5 and 6 introduce
techniques to use functions and objects to write more abstract code and
thus keep complexity under control.
After a first project chapter, the first part of the book continues with
chapters on error handling and fixing, on regular expressions (an im-
portant tool for working with text data), and on modularity—another
weapon against complexity. The second project chapter concludes the
first part of the book.
The second part, Chapters 12 to 19, describes the tools that browser
JavaScript has access to. You’ll learn to display things on the screen
(Chapters 13 and 16), respond to user input (Chapters 14 and 18), and
9
communicate over the network (Chapter 17). There are again two project
chapters in this part.
After that, Chapter 20 describes Node.js, and Chapter 21 builds a
simple web system using that tool.
Typographic conventions
In this book, text written in a monospaced font will represent elements of
programs—sometimes they are self-sufficient fragments, and sometimes
they just refer to part of a nearby program. Programs (of which you
have already seen a few), are written as follows:
function fac(n) {
if (n == 0)
return 1;
else
return fac(n - 1) * n;
}
Sometimes, in order to show the output that a program produces, the
expected output is written after it, with two slashes and an arrow in
front.
console.log(fac(8));
// ! 40320
Good luck!
10
“Below the surface of the machine, the program moves.
Without effort, it expands and contracts. In great harmony,
electrons scatter and regroup. The forms on the monitor are
but ripples on the water. The essence stays invisibly below.”
—Master Yuan-Ma, The Book of Programming
1 Values, Types, and Operators
Inside the computer’s world, there is only data. You can read data,
modify data, create new data—but anything that isn’t data simply does
not exist. All this data is stored as long sequences of bits and is thus
fundamentally alike.
Bits are any kind of two-valued things, usually described as zeros and
ones. Inside the computer, they take forms such as a high or low electrical
charge, a strong or weak signal, or a shiny or dull spot on the surface of
a CD. Any piece of discrete information can be reduced to a sequence of
zeros and ones and thus represented in bits.
For example, think about how you might show the number 13 in bits.
It works the same way you write decimal numbers, but instead of 10
different digits, you have only 2, and the weight of each increases by a
factor of 2 from right to left. Here are the bits that make up the number
13, with the weights of the digits shown below them:
0
0
0
0
1
1
0
1
128
64
32
16
8
4
2
1
So that’s the binary number 00001101, or 8 + 4 + 1, which equals 13.
Values
Imagine a sea of bits. An ocean of them. A typical modern computer
has more than 30 billion bits in its volatile data storage. Nonvolatile
storage (the hard disk or equivalent) tends to have yet a few orders of
magnitude more.
11
To be able to work with such quantities of bits without getting lost, you
can separate them into chunks that represent pieces of information. In
a JavaScript environment, those chunks are called values. Though all
values are made of bits, they play different roles. Every value has a type
that determines its role. There are six basic types of values in JavaScript:
numbers, strings, Booleans, objects, functions, and undefined values.
To create a value, you must merely invoke its name. This is convenient.
You don’t have to gather building material for your values or pay for
them. You just call for one, and woosh, you have it. They are not created
from thin air, of course. Every value has to be stored somewhere, and if
you want to use a gigantic amount of them at the same time, you might
run out of bits. Fortunately, this is a problem only if you need them all
simultaneously. As soon as you no longer use a value, it will dissipate,
leaving behind its bits to be recycled as building material for the next
generation of values.
This chapter introduces the atomic elements of JavaScript programs,
that is, the simple value types and the operators that can act on such
values.
Numbers
Values of the number type are, unsurprisingly, numeric values.
In a
JavaScript program, they are written as follows:
13
Use that in a program, and it will cause the bit pattern for the number
13 to come into existence inside the computer’s memory.
12
JavaScript uses a fixed number of bits, namely 64 of them, to store
a single number value. There are only so many patterns you can make
with 64 bits, which means that the amount of different numbers that can
be represented is limited. For N decimal digits, the amount of numbers
that can be represented is 10N . Similarly, given 64 binary digits, you
can represent 264 different numbers, which is about 18 quintillion (an 18
with 18 zeros after it). This is a lot.
Computer memory used to be a lot smaller, and people tended to
use groups of 8 or 16 bits to represent their numbers. It was easy to
accidentally overflow such small numbers—to end up with a number
that did not fit into the given amount of bits. Today, even personal
computers have plenty of memory, so you are free to use 64-bit chunks,
which means you need to worry about overflow only when dealing with
truly astronomical numbers.
Not all whole numbers below 18 quintillion fit in a JavaScript number,
though. Those bits also store negative numbers, so one bit indicates
the sign of the number. A bigger issue is that nonwhole numbers must
also be represented. To do this, some of the bits are used to store the
position of the decimal point. The actual maximum whole number that
can be stored is more in the range of 9 quadrillion (15 zeros), which is
still pleasantly huge.
Fractional numbers are written by using a dot.
9.81
For very big or very small numbers, you can also use scientific notation by
adding an “e” (for “exponent”), followed by the exponent of the number:
2.998 e8
That is 2.998 108 = 299,800,000.
Calculations with whole numbers (also called integers) smaller than
the aforementioned 9 quadrillion are guaranteed to always be precise.
Unfortunately, calculations with fractional numbers are generally not.
Just as (pi) cannot be precisely expressed by a finite number of decimal
digits, many numbers lose some precision when only 64 bits are available
to store them. This is a shame, but it causes practical problems only in
specific situations. The important thing is to be aware of it and treat
13
fractional digital numbers as approximations, not as precise values.
Arithmetic
The main thing to do with numbers is arithmetic. Arithmetic operations
such as addition or multiplication take two number values and produce
a new number from them. Here is what they look like in JavaScript:
100 + 4 * 11
The + and * symbols are called operators. The first stands for addition,
and the second stands for multiplication. Putting an operator between
two values will apply it to those values and produce a new value.
Does the example mean “add 4 and 100, and multiply the result by
11”, or is the multiplication done before the adding? As you might have
guessed, the multiplication happens first. But as in mathematics, you
can change this by wrapping the addition in parentheses.
(100 + 4) * 11
For subtraction, there is the - operator, and division can be done with
the / operator.
When operators appear together without parentheses, the order in
which they are applied is determined by the precedence of the operators.
The example shows that multiplication comes before addition. The /
operator has the same precedence as *. Likewise for + and -. When
multiple operators with the same precedence appear next to each other,
as in 1 - 2 + 1, they are applied left to right: (1 - 2)+ 1.
These rules of precedence are not something you should worry about.
When in doubt, just add parentheses.
There is one more arithmetic operator, which you might not immedi-
ately recognize. The % symbol is used to represent the remainder oper-
ation. X % Y is the remainder of dividing X by Y. For example, 314 % 100
produces 14, and 144 % 12 gives 0. Remainder’s precedence is the same as
that of multiplication and division. You’ll often see this operator referred
to as modulo, though technically remainder is more accurate.
14
This is the first line
And this is the second
There are, of course, situations where you want a backslash in a string
to be just a backslash, not a special code. If two backslashes follow each
other, they will collapse together, and only one will be left in the resulting
string value. This is how the string “A newline character is written like
"\n".” can be expressed:
"A newline character is written like \"\\n\"."
Strings cannot be divided, multiplied, or subtracted, but the + operator
can be used on them. It does not add, but it concatenates—it glues two
strings together. The following line will produce the string "concatenate":
"con" + "cat" + "e" + "nate"
There are more ways of manipulating strings, which we will discuss when
we get to methods in Chapter 4.
Unary operators
Not all operators are symbols. Some are written as words. One example
is the typeof operator, which produces a string value naming the type of
the value you give it.
console.log(typeof 4.5)
// ! number
console.log(typeof "x")
// ! string
We will use console.log in example code to indicate that we want to see
the result of evaluating something. When you run such code, the value
produced should be shown on the screen, though how it appears will
depend on the JavaScript environment you use to run it.
The other operators we saw all operated on two values, but typeof takes
only one. Operators that use two values are called binary operators,
while those that take one are called unary operators. The minus operator
can be used both as a binary operator and as a unary operator.
16
console.log(- (10 - 2))
// ! -8
Boolean values
Often, you will need a value that simply distinguishes between two pos-
sibilities, like “yes” and “no” or “on” and “off”. For this, JavaScript has
a Boolean type, which has just two values: true and false (which are
written simply as those words).
Comparisons
Here is one way to produce Boolean values:
console.log(3 > 2)
// ! true
console.log(3 < 2)
// ! false
The > and < signs are the traditional symbols for “is greater than” and
“is less than”, respectively. They are binary operators. Applying them
results in a Boolean value that indicates whether they hold true in this
case.
Strings can be compared in the same way.
console.log(" Aardvark" < "Zoroaster ")
// ! true
The way strings are ordered is more or less alphabetic: uppercase letters
are always “less” than lowercase ones, so "Z" < "a" is true, and non-
alphabetic characters (!, -, and so on) are also included in the ordering.
The actual comparison is based on the Unicode standard. This stan-
dard assigns a number to virtually every character you would ever need,
including characters from Greek, Arabic, Japanese, Tamil, and so on.
Having such numbers is useful for storing strings inside a computer be-
cause it makes it possible to represent them as a sequence of numbers.
When comparing strings, JavaScript goes over them from left to right,
comparing the numeric codes of the characters one by one.
17
Other similar operators are >= (greater than or equal to), <= (less than
or equal to), == (equal to), and != (not equal to).
console.log("Itchy" != "Scratchy ")
// ! true
There is only one value in JavaScript that is not equal to itself, and that
is NaN, which stands for “not a number”.
console.log(NaN == NaN)
// ! false
NaN is supposed to denote the result of a nonsensical computation, and as
such, it isn’t equal to the result of any other nonsensical computations.
Logical operators
There are also some operations that can be applied to Boolean values
themselves. JavaScript supports three logical operators: and, or, and
not. These can be used to “reason” about Booleans.
The && operator represents logical and. It is a binary operator, and its
result is true only if both the values given to it are true.
console.log(true && false)
// ! false
console.log(true && true)
// ! true
The || operator denotes logical or. It produces true if either of the values
given to it is true.
console.log(false || true)
// ! true
console.log(false || false)
// ! false
Not is written as an exclamation mark (!). It is a unary operator that
flips the value given to it—!true produces false and !false gives true.
When mixing these Boolean operators with arithmetic and other oper-
ators, it is not always obvious when parentheses are needed. In practice,
you can usually get by with knowing that of the operators we have seen
so far, || has the lowest precedence, then comes &&, then the comparison
18
operators (>, ==, and so on), and then the rest. This order has been
chosen such that, in typical expressions like the following one, as few
parentheses as possible are necessary:
1 + 1 == 2 && 10 * 10 > 50
The last logical operator I will discuss is not unary, not binary, but
ternary, operating on three values. It is written with a question mark
and a colon, like this:
console.log(true ? 1 : 2);
// ! 1
console.log(false ? 1 : 2);
// ! 2
This one is called the conditional operator (or sometimes just ternary
operator since it is the only such operator in the language). The value
on the left of the question mark “picks” which of the other two values
will come out. When it is true, the middle value is chosen, and when it
is false, the value on the right comes out.
Undefined values
There are two special values, written null and undefined, that are used to
denote the absence of a meaningful value. They are themselves values,
but they carry no information.
Many operations in the language that don’t produce a meaningful value
(you’ll see some later) yield undefined simply because they have to yield
some value.
The difference in meaning between undefined and null is an accident of
JavaScript’s design, and it doesn’t matter most of the time. In the cases
where you actually have to concern yourself with these values, I recom-
mend treating them as interchangeable (more on that in a moment).
Automatic type conversion
In the introduction, I mentioned that JavaScript goes out of its way
to accept almost any program you give it, even programs that do odd
19
things. This is nicely demonstrated by the following expressions:
console.log(8 * null)
// ! 0
console.log ("5" - 1)
// ! 4
console.log ("5" + 1)
// ! 51
console.log("five" * 2)
// ! NaN
console.log(false == 0)
// ! true
When an operator is applied to the “wrong” type of value, JavaScript will
quietly convert that value to the type it wants, using a set of rules that
often aren’t what you want or expect. This is called type coercion. So the
null in the first expression becomes 0, and the "5" in the second expression
becomes 5 (from string to number). Yet in the third expression, + tries
string concatenation before numeric addition, so the 1 is converted to "1"
(from number to string).
When something that doesn’t map to a number in an obvious way
(such as "five" or undefined) is converted to a number, the value NaN is
produced. Further arithmetic operations on NaN keep producing NaN, so
if you find yourself getting one of those in an unexpected place, look for
accidental type conversions.
When comparing values of the same type using ==, the outcome is easy
to predict: you should get true when both values are the same, except in
the case of NaN. But when the types differ, JavaScript uses a complicated
and confusing set of rules to determine what to do. In most cases, it just
tries to convert one of the values to the other value’s type. However,
when null or undefined occurs on either side of the operator, it produces
true only if both sides are one of null or undefined.
console.log(null == undefined);
// ! true
console.log(null == 0);
// ! false
That last piece of behavior is often useful. When you want to test
whether a value has a real value instead of null or undefined, you can
20
simply compare it to null with the == (or !=) operator.
But what if you want to test whether something refers to the precise
value false? The rules for converting strings and numbers to Boolean
values state that 0, NaN, and the empty string ("") count as false, while
all the other values count as true. Because of this, expressions like 0
== false and "" == false are also true. For cases like this, where you do
not want any automatic type conversions to happen, there are two extra
operators: === and !==. The first tests whether a value is precisely equal
to the other, and the second tests whether it is not precisely equal. So
"" === false is false as expected.
I recommend using the three-character comparison operators defen-
sively to prevent unexpected type conversions from tripping you up.
But when you’re certain the types on both sides will be the same, there
is no problem with using the shorter operators.
Short-circuiting of logical operators
The logical operators && and || handle values of different types in a
peculiar way. They will convert the value on their left side to Boolean
type in order to decide what to do, but depending on the operator and
the result of that conversion, they return either the original left-hand
value or the right-hand value.
The || operator, for example, will return the value to its left when that
can be converted to true and will return the value on its right otherwise.
This conversion works as you’d expect for Boolean values and should do
something analogous for values of other types.
console.log(null || "user")
// ! user
console.log("Karl" || "user")
// ! Karl
This functionality allows the || operator to be used as a way to fall
back on a default value. If you give it an expression that might produce
an empty value on the left, the value on the right will be used as a
replacement in that case.
The && operator works similarly, but the other way around. When the
value to its left is something that converts to false, it returns that value,
21
and otherwise it returns the value on its right.
Another important property of these two operators is that the expres-
sion to their right is evaluated only when necessary. In the case of true
|| X, no matter what X is—even if it’s an expression that does something
terrible—the result will be true, and X is never evaluated. The same goes
for false && X, which is false and will ignore X. This is called short-circuit
evaluation.
The conditional operator works in a similar way. The first expression
is always evaluated, but the second or third value, the one that is not
picked, is not.
Summary
We looked at four types of JavaScript values in this chapter: numbers,
strings, Booleans, and undefined values.
Such values are created by typing in their name (true, null) or value (13,
"abc"). You can combine and transform values with operators. We saw
binary operators for arithmetic (+, -, *, /, and %), string concatenation
(+), comparison (==, !=, ===, !==, <, >, <=, >=), and logic (&&, ||), as well as
several unary operators (- to negate a number, ! to negate logically, and
typeof to find a value’s type) and a ternary operator (?:) to pick one of
two values based on a third value.
This gives you enough information to use JavaScript as a pocket cal-
culator, but not much more. The next chapter will start tying these
expressions together into basic programs.
22
“And my heart glows bright red under my filmy, translucent
skin and they have to administer 10cc of JavaScript to get me
to come back. (I respond well to toxins in the blood.) Man,
that stuff will kick the peaches right out your gills!”
—_why, Why’s (Poignant) Guide to Ruby
2 Program Structure
In this chapter, we will start to do things that can actually be called
programming. We will expand our command of the JavaScript language
beyond the nouns and sentence fragments we’ve seen so far, to the point
where we can express some meaningful prose.
Expressions and statements
In Chapter 1, we made some values and then applied operators to them
to get new values. Creating values like this is an essential part of every
JavaScript program, but it is only a part.
A fragment of code that produces a value is called an expression. Ev-
ery value that is written literally (such as 22 or "psychoanalysis") is an
expression. An expression between parentheses is also an expression,
as is a binary operator applied to two expressions or a unary operator
applied to one.
This shows part of the beauty of a language-based interface. Expres-
sions can nest in a way very similar to the way subsentences in human
languages are nested—a subsentence can contain its own subsentences,
and so on. This allows us to combine expressions to express arbitrarily
complex computations.
If an expression corresponds to a sentence fragment, a JavaScript state-
ment corresponds to a full sentence in a human language. A program is
simply a list of statements.
The simplest kind of statement is an expression with a semicolon after
it. This is a program:
1;
!false;
It is a useless program, though. An expression can be content to just
23
produce a value, which can then be used by the enclosing expression. A
statement stands on its own and amounts to something only if it affects
the world. It could display something on the screen—that counts as
changing the world—or it could change the internal state of the machine
in a way that will affect the statements that come after it. These changes
are called side effects. The statements in the previous example just
produce the values 1 and true and then immediately throw them away.
This leaves no impression on the world at all. When executing the
program, nothing observable happens.
In some cases, JavaScript allows you to omit the semicolon at the end
of a statement. In other cases, it has to be there, or the next line will
be treated as part of the same statement. The rules for when it can
be safely omitted are somewhat complex and error-prone. In this book,
every statement that needs a semicolon will always be terminated by
one. I recommend you do the same in your own programs, at least until
you’ve learned more about subtleties involved in leaving out semicolons.
Variables
How does a program keep an internal state? How does it remember
things? We have seen how to produce new values from old values, but
this does not change the old values, and the new value has to be immedi-
ately used or it will dissipate again. To catch and hold values, JavaScript
provides a thing called a variable.
var caught = 5 * 5;
And that gives us our second kind of statement. The special word (key-
word) var indicates that this sentence is going to define a variable. It is
followed by the name of the variable and, if we want to immediately give
it a value, by an = operator and an expression.
The previous statement creates a variable called caught and uses it to
grab hold of the number that is produced by multiplying 5 by 5.
After a variable has been defined, its name can be used as an expres-
sion. The value of such an expression is the value the variable currently
holds. Here’s an example:
24
var ten = 10;
console.log(ten * ten);
// ! 100
Variable names can be any word that isn’t a reserved word (such as
var). They may not include spaces. Digits can also be part of variable
names—catch22 is a valid name, for example—but the name must not
start with a digit. A variable name cannot include punctuation, except
for the characters $ and _.
When a variable points at a value, that does not mean it is tied to
that value forever. The = operator can be used at any time on existing
variables to disconnect them from their current value and have them
point to a new one.
var mood = "light";
console.log(mood);
// ! light
mood = "dark";
console.log(mood);
// ! dark
You should imagine variables as tentacles, rather than boxes. They do
not contain values; they grasp them—two variables can refer to the same
value. A program c