Search for notes by fellow students, in your own course and all over the country.

Browse our notes for titles which look like what you need, you can preview any of the notes via a sample of the contents. After you're happy these are the notes you're after simply pop them into your shopping cart.

My Basket

You have nothing in your shopping cart yet.

Title: programming
Description: This is a principle of programming

Document Preview

Extracts from the notes are below, to see the PDF you'll receive please use the links above


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
...
0/)
...
org/licenses/MIT)
...
Computer (introduction) and unicycle people (Chapter 21) by
Max Xiantu
...
Octopuses (Chapter 2 and 4) by
Jim Tierney
...

Regular expression diagrams in Chapter 9 generated with regexper
...
Game concept for Chapter 15 by Thomas Palef
...

The second edition of Eloquent JavaScript was made possible by 454
financial backers
...
amazon
...


i

Contents
On programming
...

What is JavaScript?
...

Typographic conventions
...


...

it

...



...


...


...


1 Values, Types, and Operators
Values
...

Strings
...

Boolean values
...

Automatic type conversion
...

2 Program Structure
Expressions and statements
...

Keywords and reserved words
The environment
...

The console
...

Return values
...

Control flow
...

while and do loops
...



...


...


...


...


...


...


ii


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


2
4
6
8
9
10


...


...


...


...


11
11
12
15
16
17
19
19
22


...


...


...


...


...


...


23
23
24
26
27
27
28
28
29
30
30
32
34

for loops
...

Updating variables succinctly
...

Comments
...

Exercises
...

Parameters and scopes
...

Functions as values
...

The call stack
...

Closure
...

Growing functions
...

Exercises
...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...

Data sets
...

Methods
...

Mutability
...

Computing correlation
...

The final analysis
...

Strings and their properties
...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


42
42
43
45
46
47
48
49
50
52
55
58
58
59


...


...


...


...


...


...


61
61
62
63
64
65
68
69
71
73
74
76
78

The arguments object
The Math object
...

Summary
...



...


...


...


...


...



...


...


...

Abstracting array traversal
Higher-order functions
...

JSON
...

Transforming with map
...

Composability
...

Great-great-great-great-…
...

Summary
...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


6 The Secret Life of Objects
History
...

Prototypes
...

Overriding derived properties
Prototype interference
...

Polymorphism
...

Getters and setters
...

The instanceof operator
...

Exercises
...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


79
80
82
82
83


...


...


...


...


...


...


...


86
87
88
90
91
92
94
95
95
96
98
99
102
102
103


...


...


...


...


...


...


...


105
105
107
108
109
110
112
114
115
115
121
122
124
125
126

7 Project: Electronic Life
Definition
...

A critter’s programming interface
The world object
...

Animating life
...

More life forms
...

Action handlers
...

Bringing it to life
...

8 Bugs and Error Handling
Programmer mistakes
...

Testing
...

Error propagation
...

Cleaning up after exceptions
Selective catching
...

Summary
...



...


...


...


...


...


...

Matching a set of characters
...

Grouping subexpressions
...

The date type
...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


149
149
150
151
153
154
156
157
159
161
162
163


...


...


...


...


164
164
165
165
167
168
168
170
171

Choice patterns
...

Backtracking
...

Greed
...

The lastIndex property
...

International characters
...

Exercises
...

Using functions as namespaces
...

Detaching from the global scope
...

Require
...

Interface design
...

Exercises
...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...

The evaluator
...

The environment
...

Compilation
...

Exercises
...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...
220

vi

The Web
...

HTML and JavaScript
...

Compatibility and the browser wars
13 The Document Object Model
Document structure
...

The standard
...

Finding elements
...

Creating nodes
...

Layout
...

Cascading styles
...

Positioning and animating
...

Exercises
...

Events and DOM nodes
Event objects
...

Default actions
...

Mouse clicks
...

Scroll events
...

Load event
...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


vii


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


229
229
230
232
233
234
235
236
238
240
242
244
245
246
249
249


...


...


...


...


...


...


...
268
Summary
...
270
15 Project: A Platform Game
The game
...

Levels
...

Actors
...

Drawing
...

Actors and actions
...

Running the game
...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...


16 Drawing on Canvas
SVG
...

Filling and stroking
...

Curves
...

Text
...

Transformation
...

Choosing a graphics interface
...

Exercises
...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...
324
Browsers and HTTP
...

Sending a request
...

HTTP sandboxing
...

Promises
...

Security and HTTPS
...

Exercises
...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...

Focus
...

The form as a whole
...

Checkboxes and radio buttons
Select fields
...

Storing data client-side
...

Exercises
...

Building the DOM
...

Tool selection
...

Saving
...

Finishing up
...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...
js


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


342
342
344
345
345
347
348
349
351
353
356
357


...


...


...


...


...

Asynchronicity
...

Modules
...

The file system module
The HTTP module
...

A simple file server
...

Summary
...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...



...


...


...


...


...


...


21 Project: Skill-Sharing Website
Design
...

HTTP interface
...

The client
...

Program Structure
...

Data Structures: Objects and Arrays
Higher-Order Functions
...

Project: Electronic Life
...

Regular Expressions
...

Project: A Programming Language
...

Handling Events
...

Drawing on Canvas
...

Forms and Form Fields
...


x


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...


...



...


...


...


...


...


...


376
377
378
380
381
382
384
386
388
393
395
395


...


...


...


...


...


...


...


...


...


...


...


...
js
...
448

xi

Introduction
This is a book about getting computers to do what you want them to
do
...
To many, they remain alien, slightly threatening things
...

The first is to appeal to our sense of the physical world and build interfaces that mimic that world and allow us to manipulate shapes on a
screen with our fingers
...

But we have not yet found a good way to use the point-and-click approach to communicate things to the computer that the designer of the
interface did not anticipate
...

Human languages allow words and phrases to be combined in many
ways, which allows us to say many different things
...


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
...
One such language, JavaScript, is built into almost every web
browser and is thus available on just about every consumer device
...


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
...

—Confucius
Besides explaining JavaScript, I also will introduce the basic principles
of programming
...
The fundamental
rules are typically simple and clear
...
You’re building your own maze, in a way, and you might
just get lost in it
...

If you are new to programming, there will be a lot of new material to
digest
...

It is up to you to make the necessary effort
...
You are fine—you just need to keep at it
...
Learning is hard work, but everything
you learn is yours and will make subsequent learning easier
...
Universes of virtually unlimited

2

complexity can be created in the form of computer programs
...
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
...
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
...
Computers themselves can do only stupidly straightforward
things
...
A program can ingeniously combine an enormous
number of these simple actions in order to do very complicated things
...
A
program is a building of thought
...

But without care, a program’s size and complexity will grow out of
control, confusing even the person who created it
...
When a program
works, it is beautiful
...
The great program is subdued—made simple in its complexity
...

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
...
It is certainly dangerous going, luring the inexperienced programmer into all kinds of confusion, but that only means you should
proceed with caution and keep your wits about you
...
Programmers who refuse to keep exploring will stagnate, forget their joy, and get
bored with their craft
...
Programs looked something like this:
00110001
00110001
00110011
01010001
00100010
01000011
01000001
00010000
01100010

00000000
00000001
00000001
00001011
00000010
00000001
00000001
00000010
00000000

00000000
00000001
00000010
00000010
00001000
00000000
00000001
00000000
00000000

That is a program to add the numbers from 1 to 10 together and print
out the result: 1 + 2 +
...
It could run on a simple, hypothetical machine
...
You can probably imagine
how tedious and error-prone this procedure was
...
Complex ones were
nearly inconceivable
...
And that has to be worth something in terms of job satisfaction
...
It
could be written in English like this:
1
...

3
...

5
...

Store the number 1 in memory location 1
...

Subtract the number 11 from the value in memory location 2
...


4

6
...

8
...


Add the value of memory location 1 to memory location 0
...

Continue with instruction 3
...


Although that is already more readable than the soup of bits, it is still
rather unpleasant
...

Set " total " to 0
...

[ loop ]
Set " compare " to " count "
...

If " compare " is zero , continue at [ end ]
...

Add 1 to " count "
...

[ end ]
Output " total "
...
The lines using compare are
probably the weirdest ones
...
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
...
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
...
log ( total ) ;

5

//



55

This version gives us a few more improvements
...
The while language construct takes care of that
...
That condition is count <= 10, which means “count is
less than or equal to 10”
...
Part of the
power of programming languages is that they take care of uninteresting
details for us
...
log operation is applied to the result in order to write it as output
...
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
...
(We will see in later
chapters how to build operations like sum and range
...
It helps omit uninteresting details, provides convenient building
blocks (such as while and console
...


What is JavaScript?
JavaScript was introduced in 1995 as a way to add programs to web pages
in the Netscape Navigator browser
...
It has made modern web

6

applications possible—applications with which you can interact directly,
without doing a page reload for every action
...

It is important to note that JavaScript has almost nothing to do
with the programming language named Java
...
When
JavaScript was being introduced, the Java language was being heavily
marketed and was gaining popularity
...
Now we are stuck with the
name
...
This is called the ECMAScript standard, after the Ecma International organization that did
the standardization
...

There are those who will say terrible things about the JavaScript language
...
When I was required to write
something in JavaScript for the first time, I quickly came to despise it
...
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
...
In actuality, it mostly makes finding
problems in your programs harder because the system will not point
them out to you
...
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
...

There have been several versions of JavaScript
...
During this time, work

7

was underway on an ambitious version 4, which planned a number of
radical improvements and extensions to the language
...
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
...

Web browsers are not the only platforms on which JavaScript is used
...
Several platforms for desktop and
server programming, most notably the Node
...


Code, and what to do with it
Code is the text that makes up programs
...
In my experience, reading code and writing code
are indispensable parts of learning to program, so try to not just glance
over the examples
...
This
may be slow and confusing at first, but I promise that you will quickly
get the hang of it
...
Don’t assume you
understand them until you’ve actually written a working solution
...
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
...
net
...
To work on the exercises,
go to eloquentjavascript
...

If you want to run the programs defined in this book outside of the

8

book’s sandbox, some care is required
...
But code in later
chapters is mostly written for a specific environment (the browser or
Node
...
In addition, many chapters define
bigger programs, and the pieces of code that appear in them depend on
each other or on external files
...


Overview of this book
This book contains roughly three parts
...
The next eight chapters are about web
browsers and the way JavaScript is used to program them
...
js, another environment to program
JavaScript in
...
In
order of appearance, we will work through building an artificial life simulation, a programming language, a platform game, a paint program,
and a dynamic website
...
They introduce control
structures (such as the while word you saw in this introduction), functions
(writing your own operations), and data structures
...
Next, Chapters 5 and 6 introduce
techniques to use functions and objects to write more abstract code and
thus keep complexity under control
...
The second project chapter concludes the
first part of the book
...
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)
...

After that, Chapter 20 describes Node
...


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
...

console
...

Without effort, it expands and contracts
...
The forms on the monitor are
but ripples on the water
...

—Master Yuan-Ma, The Book of Programming

1 Values, Types, and Operators
Inside the computer’s world, there is only data
...
All this data is stored as long sequences of bits and is thus
fundamentally alike
...
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
...

For example, think about how you might show the number 13 in bits
...
Here are the bits that make up the number
13, with the weights of the digits shown below them:
0
128

0
64

0
32

0
16

1
8

1
4

0
2

1
1

So that’s the binary number 00001101, or 8 + 4 + 1, which equals 13
...
An ocean of them
...
Nonvolatile
storage (the hard disk or equivalent) tends to have yet a few orders of
magnitude more
...
In
a JavaScript environment, those chunks are called values
...
Every value has a type
that determines its role
...

To create a value, you must merely invoke its name
...

You don’t have to gather building material for your values or pay for
them
...
They are not created
from thin air, of course
...
Fortunately, this is a problem only if you need them all
simultaneously
...

This chapter introduces the atomic elements of JavaScript programs,
that is, the simple value types and the operators that can act on such
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
...
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
...
Similarly, given 64 binary digits, you
can represent 264 different numbers, which is about 18 quintillion (an 18
with 18 zeros after it)
...

Computer memory used to be a lot smaller, and people tended to
use groups of 8 or 16 bits to represent their numbers
...
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
...
Those bits also store negative numbers, so one bit indicates
the sign of the number
...
To do this, some of the bits are used to store the
position of the decimal point
...

Fractional numbers are written by using a dot
...
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 × 108 = 299,800,000
...

Unfortunately, calculations with fractional numbers are generally not
...
This is a shame, but it causes practical problems only in
specific situations
...


Arithmetic
The main thing to do with numbers is arithmetic
...
Here is what they look like in JavaScript:
100 + 4 * 11

The + and * symbols are called operators
...
Putting an operator between
two values will apply it to those values and produce a new value
...
But as in mathematics, you
can change this by wrapping the addition in parentheses
...

When operators appear together without parentheses, the order in
which they are applied is determined by the precedence of the operators
...
The /
operator has the same precedence as *
...
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
...

When in doubt, just add parentheses
...
The % symbol is used to represent the remainder operation
...
For example, 314 % 100
produces 14, and 144 % 12 gives 0
...
You’ll often see this operator referred
to as modulo, though technically remainder is more accurate
...

The first two are Infinity and -Infinity, which represent the positive
and negative infinities
...
Don’t put
too much trust in infinity-based computation
...

NaN stands for “not a number”, even though it is a value of the number
type
...


Strings
The next basic data type is the string
...
They are written by enclosing their content in quotes
...

Almost anything can be put between quotes, and JavaScript will make
a string value out of it
...
You can
imagine how putting quotes between quotes might be hard
...
The string has to stay on a single line
...
This is
called escaping the character
...
When an n character occurs
after a backslash, it is interpreted as a newline
...
Take the following string:
" This is the first line \ nAnd this is the second "

The actual text contained is this:

15

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
...
This is how the string “A newline character is written like
"\n"
...
"

Strings cannot be divided, multiplied, or subtracted, but the + operator
can be used on them
...
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
...
Some are written as words
...

console
...
5)
// → number
console
...
log in example code to indicate that we want to see
the result of evaluating something
...

The other operators we saw all operated on two values, but typeof takes
only one
...
The minus operator
can be used both as a binary operator and as a unary operator
...
log ( - (10 - 2) )
// → -8

Boolean values
Often, you will need a value that simply distinguishes between two possibilities, like “yes” and “no” or “on” and “off”
...


Comparisons
Here is one way to produce Boolean values:
console
...
log (3 < 2)
// → false

The > and < signs are the traditional symbols for “is greater than” and
“is less than”, respectively
...
Applying them
results in a Boolean value that indicates whether they hold true in this
case
...

console
...

The actual comparison is based on the Unicode standard
...

Having such numbers is useful for storing strings inside a computer because it makes it possible to represent them as a sequence of numbers
...


17

Other similar operators are >= (greater than or equal to), <= (less than
or equal to), == (equal to), and != (not equal to)
...
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”
...
log ( NaN == NaN )
// → false

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
...
JavaScript supports three logical operators: and, or, and
not
...

The && operator represents logical and
...

console
...
log ( true && true )
// → true

The || operator denotes logical or
...

console
...
log ( false || false )
// → false

Not is written as an exclamation mark (!)
...

When mixing these Boolean operators with arithmetic and other operators, it is not always obvious when parentheses are needed
...
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
...
log ( true ? 1 : 2) ;
// → 1
console
...
The value
on the left of the question mark “picks” which of the other two values
will come out
...


Undefined values
There are two special values, written null and undefined, that are used to
denote the absence of a meaningful value
...

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
...
In the cases
where you actually have to concern yourself with these values, I recommend treating them as interchangeable (more on that in a moment)
...
This is nicely demonstrated by the following expressions:
console
...
log ("5" - 1)
// → 4
console
...
log (" five " * 2)
// → NaN
console
...
This is called type coercion
...
Yet in the third expression, + tries
string concatenation before numeric addition, so the 1 is converted to "1"
(from number to string)
...
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
...
But when the types differ, JavaScript uses a complicated
and confusing set of rules to determine what to do
...
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
...
log ( null == undefined );
// → true
console
...
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
...
Because of this, expressions like 0
== false and "" == false are also true
...
The first tests whether a value is precisely equal
to the other, and the second tests whether it is not precisely equal
...

I recommend using the three-character comparison operators defensively to prevent unexpected type conversions from tripping you up
...


Short-circuiting of logical operators
The logical operators && and || handle values of different types in a
peculiar way
...

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
...

console
...
log (" Karl " || " user ")
// → Karl

This functionality allows the || operator to be used as a way to fall
back on a default value
...

The && operator works similarly, but the other way around
...

Another important property of these two operators is that the expression to their right is evaluated only when necessary
...
The same goes
for false && X, which is false and will ignore X
...

The conditional operator works in a similar way
...


Summary
We looked at four types of JavaScript values in this chapter: numbers,
strings, Booleans, and undefined values
...
You can combine and transform values with operators
...

This gives you enough information to use JavaScript as a pocket calculator, but not much more
...


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
...
) 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
...


Expressions and statements
In Chapter 1, we made some values and then applied operators to them
to get new values
...

A fragment of code that produces a value is called 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
...
Expressions 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
...

If an expression corresponds to a sentence fragment, a JavaScript statement corresponds to a full sentence in a human language
...

The simplest kind of statement is an expression with a semicolon after
it
...
An expression can be content to just

23

produce a value, which can then be used by the enclosing expression
...
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
...
The statements in the previous example just
produce the values 1 and true and then immediately throw them away
...
When executing the
program, nothing observable happens
...
In other cases, it has to be there, or the next line will
be treated as part of the same statement
...
In this book,
every statement that needs a semicolon will always be terminated by
one
...


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 immediately used or it will dissipate again
...

var caught = 5 * 5;

And that gives us our second kind of statement
...
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
...

After a variable has been defined, its name can be used as an expression
...
Here’s an example:

24

var ten = 10;
console
...
They may not include spaces
...
A variable name cannot include punctuation, except
for the characters $ and _
...
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
...
log ( mood ) ;
// → light
mood = " dark ";
console
...
They do
not contain values; they grasp them—two variables can refer to the same
value
...

When you need to remember something, you grow a tentacle to hold on
to it or you reattach one of your existing tentacles to it
...
To remember the number of dollars that Luigi
still owes you, you create a variable
...

var luigisDebt = 140;
luigisDebt = luigisDebt - 35;
console
...
If you ask for the value of an
empty variable, you’ll get the value undefined
...
The definitions
must be separated by commas
...
log ( one + two ) ;
// → 3

Keywords and reserved words
Words with a special meaning, such as var, are keywords, and they may
not be used as variable names
...
These are also officially not allowed to be used as variable names, though some JavaScript
environments do allow them
...

break case catch class const continue debugger
default delete do else enum export extends false
finally for function if implements import in
instanceof interface let new null package private
protected public return static super switch this
throw true try typeof var void while with yield

Don’t worry about memorizing these, but remember that this might be
the problem when a variable definition does not work as expected
...
When a program starts up, this environment is
not empty
...
For example, in a browser, there
are variables and functions to inspect and influence the currently loaded
website and to read mouse and keyboard input
...
A function is a piece of program wrapped in a value
...
For example,
in a browser environment, the variable alert holds a function that shows
a little dialog box with a message
...
You can
call a function by putting parentheses after an expression that produces
a function value
...
The values between the parentheses are given
to the program inside the function
...

Values given to functions are called arguments
...


27

The console
...
In past
examples, we’ve used console
...
Most JavaScript systems (including all modern web browsers and Node
...
log function that writes out its arguments to some text output device
...
This part of
the browser interface is hidden by default, but most browsers open it
when you press F12 or, on Mac, when you press Command-Option-I
...

var x = 30;
console
...
log
clearly has one
...
log isn’t a simple variable
...
We will find out exactly what this means
in Chapter 4
...
A lot of
functions are useful because of the side effects they produce
...
For example, the function Math
...

console
...
max (2 , 4) );
// → 4

When a function produces a value, it is said to return that value
...
Here a call to Math

...
max, is used as an input to the plus

28

operator:
console
...
min (2 , 4) + 100) ;
// → 102

The next chapter explains how to write your own functions
...
You can ask the user an OK/Cancel question using confirm
...

confirm (" Shall we , then ?") ;

The prompt function can be used to ask an “open” question
...
A line of text can be typed into the dialog window, and the function
will return this text as a string
...
") ;

These two functions aren’t used much in modern web programming,
mostly because you have no control over the way the resulting windows
look, but they are useful for toy programs and experiments
...
As a basic example, this
program has two statements
...

var theNumber = Number ( prompt (" Pick a number ", "") );
alert (" Your number is the square root of " +
theNumber * theNumber ) ;

The function Number converts a value to a number
...

There are similar functions called String and Boolean that convert values
to those types
...

An alternative is conditional execution, where we choose between two
different routes based on a Boolean value, like this:

Conditional execution is written with the if keyword in JavaScript
...
For example, in the previous program, we
might want to show the square of the input only if the input is actually
a number
...

The keyword if executes or skips a statement depending on the value
of a Boolean expression
...

The isNaN function is a standard JavaScript function that returns true
only if the argument it is given is NaN
...

Thus, the condition translates to “unless theNumber is not-a-number, do
this”
...
This alternate path is
represented by the second arrow in the diagram
...

var theNumber = Number ( prompt (" Pick a number ", "") );
if (! isNaN ( theNumber ) )
alert (" Your number is the square root of " +
theNumber * theNumber );
else
alert (" Hey
...
Here’s an example:
var num = Number ( prompt (" Pick a number ", "0") );
if ( num < 10)
alert (" Small ") ;
else if ( num < 100)
alert (" Medium ") ;
else
alert (" Large ") ;

The program will first check whether num is less than 10
...
If it isn’t, it takes the
else branch, which itself contains a second if
...
If it doesn’t, the second, and last, else branch is chosen
...
One way
to write this is as follows:
console
...
log (2) ;
console
...
log (6) ;
console
...
log (10) ;
console
...
If we needed all even numbers less than 1,000, the
previous would be unworkable
...
This form of control flow is called a loop:

Looping control flow allows us to go back to some point in the program
where we were before and repeat it with our current program state
...
log ( number ) ;

32

number = number + 2;
}
// → 0
// → 2
//
...
The word
while is followed by an expression in parentheses and then a statement,
much like if
...

In this loop, we want to both print the current number and add two to
our variable
...
Braces do for statements
what parentheses do for expressions: they group them together, making
them count as a single statement
...

Many JavaScript programmers wrap every single loop or if body in
braces
...
In this book, I will write most single-statement bodies
without braces, since I value brevity
...

The variable number demonstrates the way a variable can track the
progress of a program
...
Then, at the beginning of every repetition, it is compared
with the number 12 to decide whether the program has done all the work
it intended to do
...

We use two variables: one to keep track of our result and one to count
how often we have multiplied this result by 2
...

var result = 1;
var counter = 0;
while ( counter < 10) {
result = result * 2;
counter = counter + 1;
}

33

console
...

The do loop is a control structure similar to the while loop
...

To reflect this, the test appears after the body of the loop:
do {
var yourName = prompt (" Who are you ?") ;
} while (! yourName ) ;
console
...
It will ask again and again
until it gets something that is not an empty string
...
This means the loop continues going
round until you provide a name that is not the empty string
...

In JavaScript, these are not required—the computer will accept the program just fine without them
...
You could write a program as a single long line if you felt
like it
...
In complex code, where new blocks are opened
inside other blocks, it can become hard to see where one block ends and
another begins
...
I like to use two spaces
for every open block, but tastes differ—some people use four spaces, and
some people use tab characters
...
First,
a “counter” variable is created to track the progress of the loop
...
At the end of the loop body,
the counter is updated to track progress
...

for ( var number = 0; number <= 12; number = number + 2)
console
...

etcetera

This program is exactly equivalent to the earlier even-number-printing
example
...

The parentheses after a for keyword must contain two semicolons
...
The second part is the expression that checks whether the
loop must continue
...
In most cases, this is shorter and clearer than a while
construct
...
log ( result ) ;
// → 1024

Note that even though no block is opened with a {, the statement in the
loop is still indented two spaces to make it clear that it “belongs” to the
line before it
...
There is a special statement called break that has the effect of
immediately jumping out of the enclosing loop
...
It finds the first number
that is both greater than or equal to 20 and divisible by 7
...
log ( current ) ;
// → 21

Using the remainder (%) operator is an easy way to test whether a number
is divisible by another number
...

The for construct in the example does not have a part that checks for
the end of the loop
...

If you were to leave out that break statement or accidentally write a
condition that always produces true, your program would get stuck in
an infinite loop
...

The continue keyword is similar to break, in that it influences the progress
of a loop
...


Updating variables succinctly
Especially when looping, a program often needs to “update” a variable
to hold a value based on that variable’s previous value
...

This allows us to shorten our counting example a little more
...
log ( number ) ;

For counter += 1 and counter -= 1, there are even shorter equivalents: counter
++ and counter--
...
Unfortunately, the syntax JavaScript uses
for this (which it inherited from the C/Java line of programming languages) is somewhat awkward—a chain of if statements often looks better
...
log (" Remember to bring an umbrella
...
log (" Dress lightly
...
log (" Go outside
...
log (" Unknown weather type !") ;
break ;
}

You may put any number of case labels inside the block opened by switch
...
It starts
executing statements there, even if they’re under another label, until
it reaches a break statement
...
But
beware: it is easy to forget such a break, which will cause the program
to execute code you do not want executed
...
These
are pretty much your choices for writing a variable name with several
words in it:
fuzzylittleturtle
fuzzy_little_turtle
FuzzyLittleTurtle
fuzzyLittleTurtle

The first style can be hard to read
...
The standard
JavaScript functions, and most JavaScript programmers, follow the bottom style—they capitalize every word except the first
...

In a few cases, such as the Number function, the first letter of a variable
is also capitalized
...

What a constructor is will become clear in Chapter 6
...


Comments
Often, raw code does not convey all the information you want a program
to convey to human readers, or it conveys it in such a cryptic way that
people might not understand it
...
This

38

is what comments are for
...
JavaScript has two ways of writing comments
...

var accountBalance = calculateBalance ( account );
// It  s a green hollow where a river sings
accountBalance
...

var report = new Report () ;
// Where the sun on the proud mountain rings :
addToReport ( accountBalance , report ) ;
// It  s a little valley , foaming like light in a glass
...
A section of text between
/* and */ will be ignored, regardless of whether it contains line breaks
...

/*
I first found this number scrawled on the back of one of
my notebooks a few years ago
...
It obviously likes
me , so I  ve decided to keep it
...
Statements tend to contain
expressions, which themselves can be built out of smaller expressions
...
You can introduce disturbances in the flow
of control by using conditional (if, else, and switch) and looping (while,
do, and for) statements
...
The environment is the set of
variables that are defined
...

Functions are special values that encapsulate a piece of program
...
Such a
function call is an expression, and may produce a value
...

Each exercise starts with a problem description
...
If you run into problems, consider reading the hints
(!interactive after the exercise!)at the end of the book
...
net/code
...


Looping a triangle
Write a loop that makes seven calls to console
...
length after it
...
log ( abc
...
log to print all the numbers from 1
to 100, with two exceptions
...

When you have that working, modify your program to print "FizzBuzz",
for numbers that are divisible by both 3 and 5 (and still print "Fizz" or
"Buzz" for numbers divisible by only one of those)
...
So if you solved
it, you’re now allowed to feel good about yourself
...
At each position of the grid there
is either a space or a “#” character
...

Passing this string to console
...


41

“People think that computer science is the art of geniuses but
the actual reality is the opposite, just many people doing things
that build on each other, like a wall of mini stones
...
Functions are the bread and butter of JavaScript programming
...
It is a tool to
structure larger programs, to reduce repetition, to associate names with
subprograms, and to isolate these subprograms from each other
...

Creating new words in regular, human-language prose is usually bad
style
...

Typical adult English speakers have some 20,000 words in their vocabulary
...

And the vocabulary that is available tends to be more precisely defined,
and thus less flexible, than in human language
...


Defining a function
A function definition is just a regular variable definition where the value
given to the variable happens to be a function
...
log ( square (12) ) ;
// → 144

A function is created by an expression that starts with the keyword
function
...
The function body must always be wrapped in
braces, even when it consists of only a single statement (as in the previous
example)
...
In the
following example, makeNoise does not list any parameter names, whereas
power lists two:
var makeNoise = function () {
console
...
log ( power (2 , 10) );
// → 1024

Some functions produce a value, such as power and square, and some don’t,
such as makeNoise, which produces only a side effect
...
When control comes across
such a statement, it immediately jumps out of the current function and
gives the returned value to the code that called the function
...


Parameters and scopes
The parameters to a function behave like regular variables, but their
initial values are given by the caller of the function, not the code in the
function itself
...
This
means, for example, that the result variable in the power example will
be newly created every time the function is called, and these separate
incarnations do not interfere with each other
...
Variables declared outside of any function are called global, because they are
visible throughout the program
...

The following code demonstrates this
...
The first one declares the
variable as local and thus changes only the local variable
...

var x = " outside ";
var f1 = function () {
var x = " inside f1 ";
};
f1 () ;
console
...
log ( x ) ;
// → inside f2

This behavior helps prevent accidental interference between functions
...
And if you
did reuse a variable name, you might see strange effects from unrelated
code messing with the value of your variable
...


Nested scope
JavaScript distinguishes not just between global and local variables
...

For example, this rather nonsensical function has two functions inside
of it:
var landscape = function () {
var result = "";
var flat = function ( size ) {
for ( var count = 0; count < size ; count ++)
result += " _ ";
};
var mountain = function ( size ) {
result += "/";
for ( var count = 0; count < size ; count ++)
result += "  ";
result += "\\";
};
flat (3) ;
mountain (4) ;
flat (6) ;
mountain (1) ;
flat (1) ;
return result ;
};
console
...
But they cannot see each
other’s count variables since they are outside each other’s scope
...

In short, each local scope can also see all the local scopes that contain

45

it
...
All variables from blocks around a
function’s definition are visible—meaning both those in function bodies
that enclose it and those at the top level of the program
...

People who have experience with other programming languages might
expect that any block of code between braces produces a new local environment
...
You are allowed to use free-standing blocks
...

}
// Outside of the block again
...
In fact, although blocks like this are allowed, they are
useful only to group the body of an if statement or a loop
...
The next version of JavaScript
will introduce a let keyword, which works like var but creates a variable
that is local to the enclosing block, not the enclosing function
...
Such a variable is defined once and never changed
...

But the two are different
...
It is possible to store a function value in a new place, pass it as
an argument to a function, and so on
...
launch (" now ") ;

46

};
if ( safeMode )
launchMissiles = function ( value ) {/* do nothing */};

In Chapter 5, we will discuss the wonderful things that can be done by
passing around function values to other functions
...
function”
...
The statement defines the variable square
and points it at the given function
...
There is one subtlety
with this form of function definition, however
...
log (" The future says :" , future () );
function future () {
return " We STILL have no flying cars
...
This is because function declarations are not part of the
regular top-to-bottom flow of control
...

This is sometimes useful because it gives us the freedom to order code in
a way that seems meaningful, without worrying about having to define
all functions above their first use
...
Different JavaScript
platforms in different browsers have traditionally done different things
in that situation, and the latest standard actually forbids it
...

function example () {
function a () {} // Okay
if ( something ) {
function b () {} // Danger !
}
}

The call stack
It will be helpful to take a closer look at the way control flows through
functions
...
log (" Hello " + who );
}
greet (" Harry ") ;
console
...
It calls console
...
Then it reaches the end of the greet function,
so it returns to the place that called it, at line 4
...
log again
...
log
greet
top
console
...
In one case, console
...
In the other case, it jumps back to the end of the program
...

Every time a function is called, the current context is put on top of this
“stack”
...

Storing this stack requires space in the computer’s memory
...
The following code illustrates this
by asking the computer a really hard question, which causes an infinite
back-and-forth between two functions
...
As it is, we will run out of space, or
“blow the stack”
...
log ( chicken () + " came first
...
Yet when you
call it like this, it doesn’t complain
...

JavaScript is extremely broad-minded about the number of arguments
you pass to a function
...

If you pass too few, the missing parameters simply get assigned the value
undefined
...


49

The upside is that this behavior can be used to have a function take
“optional” arguments
...

function power ( base , exponent ) {
if ( exponent == undefined )
exponent = 2;
var result = 1;
for ( var count = 0; count < exponent ; count ++)
result *= base ;
return result ;
}
console
...
log ( power (4 , 3) ) ;
// → 64

In the next chapter, we will see a way in which a function body can get
at the exact list of arguments that were passed
...

For example, console
...

console
...
What happens to local variables when the function
call that created them is no longer active?
The following code shows an example of this
...
It then returns a function that
accesses and returns this local variable
...
log ( wrap1 () ) ;
// → 1
console
...
In fact, multiple instances of the variable can be alive at the
same time, which is another good illustration of the concept that local
variables really are re-created for every call—different calls can’t trample
on one another’s local variables
...
A function that “closes
over” some local variables is called a closure
...

With a slight change, we can turn the previous example into a way to
create functions that multiply by an arbitrary amount
...
log ( twice (5) ) ;
// → 10

The explicit localVariable from the wrapValue example isn’t needed since
a parameter is itself a local variable
...
A good mental
model is to think of the function keyword as “freezing” the code in its
body and wrapping it into a package (the function value)
...
}, think of it as returning a handle to a piece
of computation, frozen for later use
...
The last line then calls the value in this
variable, causing the frozen code (return number * factor;) to be activated
...


Recursion
It is perfectly okay for a function to call itself, as long as it takes care
not to overflow the stack
...

Recursion allows some functions to be written in a different style
...
log ( power (2 , 3) ) ;
// → 8

This is rather close to the way mathematicians define exponentiation
and arguably describes the concept in a more elegant way than the looping variant does
...

But this implementation has one important problem: in typical JavaScript
implementations, it’s about 10 times slower than the looping version
...

The dilemma of speed versus elegance is an interesting one
...
Almost any program can be made faster by making it bigger
and more convoluted
...

In the case of the earlier power function, the inelegant (looping) version
is still fairly simple and easy to read
...
Often, though, a program deals
with such complex concepts that giving up some efficiency in order to
make the program more straightforward becomes an attractive choice
...
If it is, find out which
parts are taking up the most time, and start exchanging elegance for
efficiency in those parts
...
In many cases, like the power function, not much simplicity
is gained from the “elegant” approach
...

The reason I’m stressing this is that surprisingly many beginning programmers focus fanatically on efficiency, even in the smallest details
...

But recursion is not always just a less-efficient alternative to looping
...
Most often these are problems that require exploring or processing several “branches”, each of which might branch out again into more
branches
...
How would you write a function that, given a number, tries to find a sequence of such additions and multiplications that
produce that number? For example, the number 13 could be reached by
first multiplying by 3 and then adding 5 twice, whereas the number 15
cannot be reached at all
...
log ( findSolution (24) );
// → (((1 * 3) + 5) * 3)

Note that this program doesn’t necessarily find the shortest sequence of
operations
...

I don’t necessarily expect you to see how it works right away
...

The inner function find does the actual recursing
...

To do this, the function performs one of three actions
...
If the current number is greater than
the target, there’s no sense in further exploring this history since both
adding and multiplying will only make the number bigger
...
If the first call returns something that is not
null, it is returned
...

To better understand how this function produces the effect we’re looking for, let’s look at all the calls to find that are made when searching
for a solution for the number 13
...
The first time find
is called it calls itself twice to explore the solutions that start with (1 + 5)
and (1 * 3)
...
Since it doesn’t find a solution that
hits the target, it returns null back to the first call
...
This search has more
luck because its first recursive call, through yet another recursive call,
hits upon the target number, 13
...


Growing functions
There are two more or less natural ways for functions to be introduced
into programs
...
We want to avoid doing that since having more code means more
space for mistakes to hide and more material to read for people trying
to understand the program
...

The second way is that you find you need some functionality that you
haven’t written yet and that sounds like it deserves its own function
...
You
might even start writing code that uses the function before you actually
define the function itself
...
Let’s go through

55

an example
...

007 Cows
011 Chickens

That clearly asks for a function of two arguments
...

function printFarmInventory ( cows , chickens ) {
var cowString = String ( cows );
while ( cowString
...
log ( cowString + " Cows ") ;
var chickenString = String ( chickens );
while ( chickenString
...
log ( chickenString + " Chickens ") ;
}
printFarmInventory (7 , 11) ;

Adding
...

Thus, the while loops keep adding zeros in front of the number strings
until they are at least three characters long
...
But just as we’re in the process of copying and pasting
those four lines one more time, we stop and reconsider
...
Here’s a first attempt:
function printZeroPaddedWithLabel ( number , label ) {
var numberString = String ( number );
while ( numberString
...
log ( numberString + " " + label );
}

56

function printFarmInventory ( cows , chickens , pigs ) {
printZeroPaddedWithLabel ( cows , " Cows ") ;
printZeroPaddedWithLabel ( chickens , " Chickens ") ;
printZeroPaddedWithLabel ( pigs , " Pigs ") ;
}
printFarmInventory (7 , 11 , 3) ;

It works! But that name, printZeroPaddedWithLabel, is a little awkward
...

Instead of lifting out the repeated part of our program wholesale, let’s
try to pick out a single concept
...
length < width )
string = "0" + string ;
return string ;
}
function printFarmInventory ( cows , chickens , pigs ) {
console
...
log ( zeroPad ( chickens , 3) + " Chickens ") ;
console
...
And it is useful
in more situations than just this specific program
...

How smart and versatile should our function be? We could write anything from a terribly simple function that simply pads a number so
that it’s three characters wide to a complicated generalized numberformatting system that handles fractional numbers, negative numbers,
alignment of dots, padding with different characters, and so on
...
It can be tempting to write general “frameworks”
for every little bit of functionality you come across
...
You

57

won’t get any real work done, and you’ll end up writing a lot of code
that no one will ever use
...
(Though it is
definitely also possible to have both side effects and return a value
...
The second version, zeroPad, is
called for its return value
...
Functions that create values are easier
to combine in new ways than functions that directly perform side effects
...
A pure function has the pleasant property that,
when called with the same arguments, it always produces the same value
(and doesn’t do anything else)
...
A
call to such a function can be mentally substituted by its result, without
changing the meaning of the code
...
Nonpure functions might return different values based on all kinds of factors
and have side effects that might be hard to test and think about
...
Side effects
are often useful
...
log, for example, and console
...
Some operations
are also easier to express in an efficient way when we use side effects, so
computing speed can be a reason to avoid purity
...
The function
keyword, when used as an expression, can create a function value
...

// Create a function value f
var f = function ( a ) {
console
...
5;
}

A key aspect in understanding functions is understanding local scopes
...
Functions declared inside another function have access to
the outer function’s local scope
...
You won’t have to repeat yourself as much, and functions can
make a program more readable by grouping code into conceptual chunks,
in the same way that chapters and sections help organize regular text
...
min that returns its smallest argument
...
Write a
function min that takes two arguments and returns their minimum
...
Here’s another way to define whether a positive whole number is
even or odd:
• Zero is even
...

• For any other number N, its evenness is the same as N - 2
...
The
function should accept a number parameter and return a Boolean
...
See how it behaves on -1
...

charAt(N), similar to how you get its length with "s"
...
The returned
value will be a string containing only one character (for example, "b"
)
...
length - 1
...

Write a function countBs that takes a string as its only argument and
returns a number that indicates how many uppercase “B” characters are
in the string
...
Rewrite
countBs to make use of this new function
...
Babbage, if
you put into the machine wrong figures, will the right answers
come out?’ […] I am not able rightly to apprehend the kind of
confusion of ideas that could provoke such a question
...
But you can’t make much of a house out of a single brick
...

The programs we have built so far have been seriously hampered by the
fact that they were operating only on simple data types
...
By the
end of it, you’ll know enough to start writing some useful programs
...

The example code will often build on functions and variables that were
introduced earlier in the text
...
net/code)
provides a way to run code in the context of a specific chapter
...


The weresquirrel
Every now and then, usually between eight and ten in the evening,
Jacques finds himself transforming into a small furry rodent with a bushy
tail
...
Turning into a squirrel tends to cause fewer problems than
turning into a wolf
...
After two occasions where he woke up on a precari-

61

ously thin branch in the crown of an oak, naked and disoriented, he has
taken to locking the doors and windows of his room at night and putting
a few walnuts on the floor to keep himself busy
...
But Jacques still suffers
from his condition
...
For a while, he
believed that it happened only on days when he had touched trees
...

But the problem persisted
...
With this data he hopes to narrow down the conditions that trigger the transformations
...


Data sets
To work with a chunk of digital data, we’ll first have to find a way to
represent it in our machine’s memory
...

We could get creative with strings—after all, strings can be any length,
so we can put a lot of data into them—and use "2 3 5 7 11" as our representation
...
You’d have to somehow extract the
digits and convert them back to numbers to access them
...
It is called an array and is written as a list of values
between square brackets, separated by commas
...
log ( listOfNumbers [1]) ;
// → 3
console
...
A pair of square brackets immediately after an expression, with
another expression inside of them, will look up the element in the lefthand expression that corresponds to the index given by the expression
in the brackets
...
So the first element can be
read with listOfNumbers[0]
...
But zero-based counting has a long tradition in technology, and as long as this convention is
followed consistently (which it is, in JavaScript), it works well
...
length (to
get the length of a string) and Math
...
These are expressions that access a property of some value
...
In
the second, we access the property named max in the Math object (which
is a collection of mathematics-related values and functions)
...
The exceptions are null
and undefined
...

null
...
Both value
...
The difference is in how

63

is interpreted
...
When using square
brackets, the expression between the brackets is evaluated to get the
property name
...
x fetches the property of value named
“x”, value[x] tries to evaluate the expression x and uses the result as the
property name
...
length
...
And because property
names can be any string, if you want to access a property named “2” or
“John Doe”, you must use square brackets: value[2] or value["John Doe"]
...

The elements in an array are stored in properties
...
The
length property of an array tells us how many elements it contains
...
length because
that is easier to write than array["length"]
...

var doh = " Doh ";
console
...
toUpperCase );
// → function
console
...
toUpperCase () );
// → DOH

Every string has a toUpperCase property
...

There is also toLowerCase
...

Interestingly, even though the call to toUpperCase does not pass any
arguments, the function somehow has access to the string "Doh", the

64

value whose property we called
...

Properties that contain functions are generally called methods of the
value they belong to
...

This example demonstrates some methods that array objects have:
var mack = [];
mack
...
push (" the " , " Knife ") ;
console
...
log ( mack
...
log ( mack
...
log ( mack ) ;
// → [" Mack ", " the "]

The push method can be used to add values to the end of an array
...
An array of strings can be flattened to a single
string with the join method
...


Objects
Back to the weresquirrel
...
But the entries do not consist of just a number or a string—
each entry needs to store a list of activities and a Boolean value that
indicates whether Jacques turned into a squirrel
...

Values of the type object are arbitrary collections of properties, and we
can add or remove these properties as we please
...

var day1 = {
squirrel : false ,
events : [" work " , " touched tree ", " pizza ", " running ",

65

" television "]
};
console
...
squirrel ) ;
// → false
console
...
wolf ) ;
// → undefined
day1
...
log ( day1
...
Each property is written as a name, followed by a colon, followed by an expression that provides a value for the property
...
When an object spans multiple lines,
indenting it like in the previous example improves readability
...

var descriptions = {
work : " Went to work " ,
" touched tree ": " Touched a tree "
};

This means that curly braces have two meanings in JavaScript
...
In any other
position, they describe an object
...

Reading a property that doesn’t exist will produce the value undefined,
which happens the first time we try to read the wolf property in the
previous example
...
This will replace the property’s value if it already existed or
create a new property on the object if it didn’t
...
They grasp values, but other variables and properties might be holding onto those same values
...


66

The delete operator cuts off a tentacle from such an octopus
...
This is not a common thing
to do, but it is possible
...
log ( anObject
...
left ;
console
...
left );
// → undefined
console
...
log (" right " in anObject );
// → true

The binary in operator, when applied to a string and an object, returns a
Boolean value that indicates whether that object has that property
...

Arrays, then, are just a kind of object specialized for storing sequences
of things
...
You can
see them as long, flat octopuses with all their arms in a neat row, labeled
with numbers
...

var journal = [
{ events : [" work " , " touched tree ", " pizza ",
" running " , " television "] ,
squirrel : false } ,
{ events : [" work " , " ice cream ", " cauliflower ",
" lasagna " , " touched tree ", " brushed teeth "] ,
squirrel : false } ,
{ events : [" weekend " , " cycling ", " break ",
" peanuts " , " beer "] ,
squirrel : true } ,
/* and so on
...
But first, there’s one
last piece of theory to understand
...
The types of values
discussed in earlier chapters, such as numbers, strings, and Booleans,
are all immutable—it is impossible to change an existing value of those
types
...
The text inside it cannot be changed
...

With objects, on the other hand, the content of a value can be modified
by changing its properties
...
But with objects, there is a difference between having two references to the same object and having two different objects that contain
the same properties
...
log ( object1 == object2 );
// → true
console
...
value = 15;
console
...
value ) ;
// → 15
console
...
value ) ;
// → 10

The object1 and object2 variables grasp the same object, which is why
changing object1 also changes the value of object2
...

JavaScript’s == operator, when comparing objects, will return true only
if both objects are precisely the same value
...
There is no “deep”
comparison operation built into JavaScript, which looks at object’s contents, but it is possible to write it yourself (which will be one of the
exercises at the end of this chapter)
...


69

var journal = [];
function addEntry ( events , didITurnIntoASquirrel ) {
journal
...

addEntry ([" work " , " touched tree ", " pizza ", " running ",
" television "] , false ) ;
addEntry ([" work " , " ice cream ", " cauliflower ", " lasagna ",
" touched tree ", " brushed teeth "] , false );
addEntry ([" weekend " , " cycling " , " break ", " peanuts ",
" beer "] , true );

Once he has enough data points, he intends to compute the correlation
between his squirrelification and each of the day’s events and ideally
learn something useful from those correlations
...
It is usually expressed
as a coefficient that ranges from -1 to 1
...

Negative one also means that the variables are perfectly related but that
they are opposites—when one is true, the other is false
...
To compute
φ, we need a table n that contains the number of times the various
combinations of the two variables were observed
...
1)

The notation n01 indicates the number of measurements where the first
variable (squirrelness) is false (0) and the second variable (pizza) is true
(1)
...

The value n1• refers to the sum of all measurements where the first
variable is true, which is 5 in the example table
...

So for the pizza table, the part above the division line (the dividend)
would be 1×76 - 4×9 = 40, and the part below it (the divisor) would

be the square root of 5×85×10×80, or 340000
...
069, which is tiny
...


Computing correlation
We can represent a two-by-two table in JavaScript with a four-element
array ([76, 9, 4, 1])
...
We’ll

71

interpret the indices to the array as two-bit binary number, where the
leftmost (most significant) digit refers to the squirrel variable and the
rightmost (least significant) digit refers to the event variable
...
This happened four
times
...

This is the function that computes the φ coefficient from such an array:
function phi ( table ) {
return ( table [3] * table [0] - table [2] * table [1]) /
Math
...
log ( phi ([76 , 9 , 4, 1]) ) ;
// → 0
...
Math

...
We have to sum two fields from the
table to get fields like n1• because the sums of rows or columns are not
stored directly in our data structure
...
The resulting data set is
available in the coding sandbox for this chapter(eloquentjavascript
...

To extract a two-by-two table for a specific event from this journal, we
must loop over all the entries and tally up how many times the event
occurs in relation to squirrel transformations
...
events
...
length ; i ++) {
var entry = journal [i] , index = 0;

72

if ( hasEvent ( event , entry ) ) index += 1;
if ( entry
...
log ( tableFor (" pizza ", JOURNAL ));
// → [76 , 9 , 4 , 1]

The hasEvent function tests whether an entry contains a given event
...
So if the call to indexOf doesn’t return -1,
then we know the event was found in the entry
...
The loop then adds one to the number in the array
that corresponds to this box on the table
...

The only step remaining is to find a correlation for every type of event
that was recorded and see whether anything stands out
...
But that makes looking up the correlation
for a given event somewhat cumbersome: you’d have to loop over the
whole array to find the object with the right name
...

A better way is to use object properties named after the event types
...


73

var map = {};
function storePhi ( event , phi ) {
map [ event ] = phi ;
}
storePhi (" pizza " , 0
...
081) ;
console
...
log ( map [" touched tree "]) ;
// → -0
...

There are a few potential problems with using objects like this, which
we will discuss in Chapter 6, but for the time being, we won’t worry
about those
...
JavaScript
provides a loop construct specifically for going over the properties of
an object
...

for ( var event in map )
console
...
069
// → The correlation for  touched tree  is -0
...

We keep an object phis that has correlation coefficients for all the event
types we have seen so far
...


74

function gatherCorrelations ( journal ) {
var phis = {};
for ( var entry = 0; entry < journal
...
events ;
for ( var i = 0; i < events
...
log ( correlations
...
068599434

Let’s see what came out
...
log ( event + ": " + correlations [ event ]) ;
// → carrot :
0
...
0685994341
// → weekend : 0
...
0757554019
// → pudding : -0
...


Most correlations seem to lie close to zero
...
It does seem
to occur somewhat more often on weekends, however
...
1 or less than -0
...

for ( var event in correlations ) {
var correlation = correlations [ event ];
if ( correlation > 0
...
1)
console
...
1371988681
// → brushed teeth : -0
...
1296407447
// → work :
-0
...
2425356250

75

//
//




reading :
peanuts :

0
...
5902679812

A-ha! There are two factors whose correlation is clearly stronger than
the others
...

Interesting
...

for ( var i = 0; i < JOURNAL
...
events
...
log ( phi ( tableFor (" peanut teeth ", JOURNAL )));
// → 1

Well, that’s unmistakable! The phenomenon occurs precisely when Jacques
eats peanuts and fails to brush his teeth
...

Knowing this, Jacques simply stops eating peanuts altogether and finds
that this completely puts an end to his transformations
...
But a few years later, he loses
his job and is eventually forced to take employment with a circus, where
he performs as The Incredible Squirrelman by stuffing his mouth with
peanut butter before every show
...
He is never seen
again
...
We’ll start by introducing some generally useful
array methods
...
The corresponding methods for adding
and removing things at the start of an array are called unshift and shift
...
push ( task ) ;
}
function whatIsNext () {
return todoList
...
unshift ( task );
}

The previous program manages lists of tasks
...
The urgentlyRememberTo function also adds a task but adds it to
the front instead of the back of the list
...

console
...
indexOf (2) );
// → 1
console
...
lastIndexOf (2) );
// → 3

Both indexOf and lastIndexOf take an optional second argument that indicates where to start searching from
...
The start index is inclusive, the end index exclusive
...
log ([0 , 1 , 2 , 3 , 4]
...
log ([0 , 1 , 2 , 3 , 4]
...
Strings also have a slice method, which has a similar
effect
...
The following example shows both concat
and slice in action
...

function remove ( array , index ) {
return array
...
concat ( array
...
log ( remove ([" a " , " b ", " c", "d", "e "] , 2) );
// → [" a ", " b" , " d " , " e "]

Strings and their properties
We can read properties like length and toUpperCase from string values
...

var myString = " Fido ";
myString
...
log ( myString
...
The values are immutable and
cannot be changed
...
Every string value
has a number of methods
...

console
...
slice (4 , 7) ) ;
// → nut
console
...
indexOf (" u ") );
// → 5

One difference is that a string’s indexOf can take a string containing more
than one character, whereas the corresponding array method looks only
for a single element
...
log (" one two three "
...

console
...
trim () ) ;

We have already seen the string type’s length property
...

var string = " abc ";
console
...
length );
// → 3
console
...
charAt (0) ) ;
// → a
console
...
This variable refers
to an object that holds all of the arguments passed to the function
...

function noArguments () {}
noArguments (1 , 2 , 3) ; // This is okay
function threeArguments (a , b , c ) {}
threeArguments () ; // And so is this

The arguments object has a length property that tells us the number of
arguments that were really passed to the function
...

If that sounds a lot like an array to you, you’re right, it is a lot like an
array
...

function argumentCounter () {

79

console
...
length , " arguments
...


Some functions can take any number of arguments, like console
...

These typically loop over the values in their arguments object
...
For example, remember how
we created the entries to Jacques’ journal
...

function addEntry ( squirrel ) {
var entry = { events : [] , squirrel : squirrel };
for ( var i = 1; i < arguments
...
events
...
push ( entry ) ;
}
addEntry ( true , " work " , " touched tree ", " pizza ",
" running " , " television ") ;

This version reads its first argument (squirrel) in the normal way and
then goes over the rest of the arguments (the loop starts at index 1,
skipping the first) to gather them into an array
...
max (maximum), Math
...
sqrt (square
root)
...
There is only one Math object, and it is almost never useful
as a value
...

Having too many global variables “pollutes” the namespace
...
For example, it’s not unlikely
that you’ll want to name something max in one of your programs
...

Many languages will stop you, or at least warn you, when you are
defining a variable with a name that is already taken
...

Back to the Math object
...

It contains cos (cosine), sin (sine), and tan (tangent), as well as their
inverse functions, acos, asin, and atan, respectively
...
PI
...
)
function randomPointOnCircle ( radius ) {
var angle = Math
...
PI ;
return {x : radius * Math
...
sin ( angle ) };
}
console
...
3667 , y : 1
...
When they are used in this book, in Chapter 13, I’ll explain them
...
random
...

console
...
random () ) ;
// → 0
...
log ( Math
...
727367032552138
console
...
random () ) ;
// → 0
...
To do this, the machine keeps a number (or a bunch of numbers) in its internal state
...
The machine also uses the outcome to change its
own internal state so that the next “random” number produced will be
different
...
floor (which rounds down to the nearest whole number) on the
result of Math
...

console
...
floor ( Math
...
Since Math
...

There are also the functions Math
...
round (to the nearest whole number)
...
Each global variable is present as
a property of this object
...

var myVar = 10;
console
...
log ( window
...
Conceptually, this allows us
to put a bunch of related things in a bag and run around with the bag,
instead of trying to wrap our arms around all of the individual things

82

and trying to hold on to them separately
...
Properties are accessed using value
...
Objects tend to use names for their properties and store
more or less a fixed set of them
...

There are some named properties in arrays, such as length and a number
of methods
...

Objects can also serve as maps, associating values with names
...
The same keyword can also be used in a for loop
(for (var name in object)) to loop over an object’s properties
...
log ( sum ( range (1 , 10) ));

Write a range function that takes two arguments, start and end, and
returns an array containing all the numbers from start up to (and including) end
...
Run the previous program and see whether
it does indeed return 55
...
If no step is given, the array elements go up by increments of
one, corresponding to the old behavior
...
Make sure it also works with negative step
values so that range(5, 2, -1) produces [5, 4, 3, 2]
...
For this exercise, write two functions,
reverseArray and reverseArrayInPlace
...
The second, reverseArrayInPlace, does what the reverse
method does: it modifies the array given as argument in order to reverse
its elements
...

Thinking back to the notes about side effects and pure functions in
the previous chapter, which variant do you expect to be useful in more
situations? Which one is more efficient?

A list
Objects, as generic blobs of values, can be used to build all sorts of data
structures
...
A list is a nested set of objects, with the first object holding
a reference to the second, the second to the third, and so on
...

For example, if I create two new values {value: 0, rest: list} and {value:
-1, rest: list} (with list referring to the variable defined earlier), they

84

are both independent lists, but they share the structure that makes up
their last three elements
...

Write a function arrayToList that builds up a data structure like the
previous one when given [1, 2, 3] as argument, and write a listToArray
function that produces an array from a list
...

If you haven’t already, also write a recursive version of nth
...
But sometimes, you would
prefer to compare the values of their actual properties
...

To find out whether to compare two things by identity (use the ===
operator for that) or by looking at their properties, you can use the
typeof operator
...
But you have to take one silly exception into account:
by a historical accident, typeof null also produces "object"
...

—C
...
R
...
Size almost always involves complexity, and complexity
confuses programmers
...
A large program also provides a lot
of space for these bugs to hide, making them hard to find
...
The first is self-contained and six lines long
...
log ( total ) ;

The second relies on two external functions and is one line long
...
log ( sum ( range (1 , 10) ));

Which one is more likely to contain a bug?
If we count the size of the definitions of sum and range, the second
program is also big—even bigger than the first
...

It is more likely to be correct because the solution is expressed in a
vocabulary that corresponds to the problem being solved
...
It is about ranges and
sums
...
But because they
are expressing simpler concepts than the program as a whole, they are
easier to get right
...
Abstractions hide details and give us the ability to
talk about problems at a higher (or more abstract) level
...
Add water
until the peas are well covered
...
Take the peas out of the water and put them
in a cooking pan
...
Cover the
pan and keep the peas simmering for two hours
...
Cut it into pieces with a knife
...
Take a stalk of celery per person
...
Add it to the peas
...

Cut it into pieces
...
Cook for
10 more minutes
...

Soak peas for 12 hours
...
Chop and add vegetables
...

The second is shorter and easier to interpret
...

When programming, we can’t rely on all the words we need to be
waiting for us in the dictionary
...

It has to become second nature, for a programmer, to notice when a
concept is begging to be abstracted into a new word
...
But sometimes they fall short
...
length ; i ++) {
var current = array [ i ];
console
...

But it uses a roundabout way that involves a counter variable i, a check
against the array’s length, and an extra variable declaration to pick out
the current element
...
We might accidentally reuse the
i variable, misspell length as lenght, confuse the i and current variables,
and so on
...
Can you think of a way?
Well, it’s easy to write a function that goes over an array and calls
console
...

function logEach ( array ) {
for ( var i = 0; i < array
...
log ( array [ i ]) ;
}

But what if we want to do something other than logging the elements?
Since “doing something” can be represented as a function and functions
are just values, we can pass our action as a function value
...
length ; i ++)
action ( array [ i ]) ;
}
forEach ([" Wampeter " , " Foma " , " Granfalloon "] , console
...
log in this way does not work
...
log if this example fails to work
...

var numbers = [1 , 2 , 3 , 4 , 5] , sum = 0;
forEach ( numbers , function ( number ) {
sum += number ;
}) ;
console
...
However, now the body is inside the function value, as
well as inside the parentheses of the call to forEach
...

Using this pattern, we can specify a variable name for the current
element (number), rather than having to pick it out of the array manually
...
It is available as a
standard method on arrays
...

To illustrate how helpful this is, let’s look back at a function from the
previous chapter
...

function gatherCorrelations ( journal ) {
var phis = {};
for ( var entry = 0; entry < journal
...
events ;
for ( var i = 0; i < events
...

function gatherCorrelations ( journal ) {

89

var phis = {};
journal
...
events
...
If you
have already accepted the fact that functions are regular values, there
is nothing particularly remarkable about the fact that such functions
exist
...

Higher-order functions allow us to abstract over actions, not just values
...
For example, you can have functions
that create new functions
...
log ( greaterThan10 (11) ) ;
// → true

And you can have functions that change other functions
...
log (" calling with ", arg ) ;
var val = f ( arg ) ;
console
...

function unless ( test , then ) {
if (! test ) then () ;
}
function repeat ( times , body ) {
for ( var i = 0; i < times ; i ++) body (i);
}
repeat (3 , function ( n ) {
unless ( n % 2, function () {
console
...
In the previous example, the n
variable is a parameter to the outer function
...
The bodies
of such inner functions can access the variables around them
...
An important difference is that variables declared inside
inner functions do not end up in the environment of the outer function
...


Passing along arguments
The noisy function defined earlier, which wraps its argument in another
function, has a rather serious deficit
...
log (" calling with ", arg ) ;
var val = f ( arg ) ;
console
...
We could
add a bunch of arguments to the inner function (arg1, arg2, and so on)
and pass them all to f, but it is not clear how many would be enough
...
length
...

For these kinds of situations, JavaScript functions have an apply method
...

function transparentWrapping ( f ) {
return function () {
return f
...
It does this by passing its own arguments object to apply
...
We will come back to that in the next
chapter
...
The forEach method is the most
primitive such function
...
To familiarize ourselves with them, let’s play
around with another data set
...
I opened it hoping to find knights, pirates, and alchemists
… but the book turns out to be mostly full of Flemish farmers
...

The file I created looks something like this:
[
{" name ": " Emma de Milliano ", " sex ": "f",
" born ": 1876 , " died ": 1956 ,
" father ": " Petrus de Milliano " ,
" mother ": " Sophia van Damme "} ,
{" name ": " Carolus Haverbeke " , " sex ": "m",
" born ": 1832 , " died ": 1905 ,
" father ": " Carel Haverbeke " ,
" mother ": " Maria van Brussel "} ,
...
It is widely used as a data storage and
communication format on the Web
...
All property names have to be surrounded by double
quotes, and only simple data expressions are allowed—no function calls,
variables, or anything that involves actual computation
...

JavaScript gives us functions, JSON
...
parse, that convert
data from and to this format
...
The second takes such a string and
converts it to the value it encodes
...
stringify ({ name : "X", born : 1980}) ;
console
...
log ( JSON
...
born );
// → 1980

The variable ANCESTRY_FILE, available in the sandbox for this chapter and
in a downloadable file on the website(eloquentjavascript
...
Let’s decode it and see
how many people it contains
...
parse ( ANCESTRY_FILE );
console
...
length ) ;

93

//



39

Filtering an array
To find the people in the ancestry data set who were young in 1924,
the following function might be helpful
...

function filter ( array , test ) {
var passed = [];
for ( var i = 0; i < array
...
push ( array [i ]) ;
}
return passed ;
}
console
...
born > 1900 && person
...
]

This uses the argument named test, a function value, to fill in a “gap”
in the computation
...

Three people in the file were alive and young in 1924: my grandfather,
grandmother, and great-aunt
...
This function is pure
...

Like forEach, filter is also a standard method on arrays
...
From
now on, we’ll use it like this instead:
console
...
filter ( function ( person ) {
return person
...
}]

94

Transforming with map
Say we have an array of objects representing people, produced by filtering
the ancestry array somehow
...

The map method transforms an array by applying a function to all of its
elements and building a new array from the returned values
...

function map ( array , transform ) {
var mapped = [];
for ( var i = 0; i < array
...
push ( transform ( array [ i ]) );
return mapped ;
}
var overNinety = ancestry
...
died - person
...
log ( map ( overNinety , function ( person ) {
return person
...
I guess medicine has come a long way
...


Summarizing with reduce
Another common pattern of computation on arrays is computing a single value from them
...
Another example would be finding the
person with the earliest year of birth in the data set
...
You can think of it as folding up the array, one
element at a time
...

The parameters to the reduce function are, apart from the array, a combining function and a start value
...

function reduce ( array , combine , start ) {
var current = start ;
for ( var i = 0; i < array
...
log ( reduce ([1 , 2 , 3 , 4] , function (a , b) {
return a + b;
}, 0) ) ;
// → 10

The standard array method reduce, which of course corresponds to this
function, has an added convenience
...
The method
will take the first element of the array as its start value and start reducing
at the second element
...
log ( ancestry
...
born < min
...
}

Composability
Consider how we would have written the previous example (finding the
person with the earliest year of birth) without higher-order functions
...


96

var min = ancestry [0];
for ( var i = 1; i < ancestry
...
born < min
...
log ( min ) ;
// → { name : " Pauwels van Haverbeke " , born : 1535 ,
...

Higher-order functions start to shine when you need to compose functions
...

function average ( array ) {
function plus (a , b ) { return a + b; }
return array
...
length ;
}
function age ( p ) { return p
...
born ; }
function male ( p ) { return p
...
sex == "f "; }
console
...
filter ( male )
...
67
console
...
filter ( female )
...
56

(It’s a bit silly that we have to define plus as a function, but operators
in JavaScript, unlike functions, are not values, so you can’t pass them
as arguments
...
We can apply these one by one to get the result we
are looking for
...
Unfortunately, this clarity
comes at a cost
...

A program that processes an array is most elegantly expressed as a
sequence of cleanly separated steps that each do something with the
array and produce a new array
...

Likewise, passing a function to forEach and letting that method handle
the array iteration for us is convenient and easy to read
...

And so it goes with a lot of techniques that help improve the clarity
of a program
...
This is not an iron law—there are programming languages that have better support for building abstractions
without adding inefficiencies, and even in JavaScript, an experienced
programmer can find ways to write abstract code that is still fast
...

Fortunately, most computers are insanely fast
...

It is helpful to roughly keep track of how often a piece of your program
is going to run
...
If that inner loop contains another loop that makes P
rounds, its body will run M ×N ×P times, and so on
...


98

Great-great-great-great-…
My grandfather, Philibert Haverbeke, is included in the data file
...

And if he is, I would like to know how much DNA I theoretically share
with him
...

var byName = {};
ancestry
...
name ] = person ;
}) ;
console
...
}

Now, the problem is not entirely as simple as following the father properties and counting how many we need to reach Pauwels
...
This causes the branches of the family tree to
rejoin in a few places, which means I share more than 1/2G of my genes
with this person, where G for the number of generations between Pauwels
and me
...

A reasonable way to think about this problem is to look at it as being analogous to reduce, which condenses an array to a single value by
repeatedly combining values, left to right
...
The shape of the data is that of a family tree, rather than
a flat list
...
This can be
done recursively: if we are interested in person A, we have to compute
the values for A’s parents, which in turn requires us to compute the value
for A’s grandparents, and so on
...
We’ll allow a default value to be given to our reduction
function, which will be used for people who are not in the data
...

Given a person, a function to combine values from the two parents of a
given person, and a default value, reduceAncestors condenses a value from
a family tree
...
mother ]) ,
valueFor ( byName [ person
...
Through the magic
of recursion, it can simply call itself to handle the father and the mother
of this person
...

We can then use this to compute the amount of DNA my grandfather
shared with Pauwels van Haverbeke and divide that by four
...
name == " Pauwels van Haverbeke ")
return 1;
else
return ( fromMother + fromFather ) / 2;
}
var ph = byName [" Philibert Haverbeke "];
console
...
00049

The person with the name Pauwels van Haverbeke obviously shared 100
percent of his DNA with Pauwels van Haverbeke (there are no people
who share names in the data set), so the function returns 1 for him
...


100

So, statistically speaking, I share about 0
...
It should be noted that this is only a statistical
approximation, not an exact amount
...

We could also have computed this number without relying on reduceAncestors

...
For example, the following code finds the percentage of a person’s
known ancestors who lived past 70 (by lineage, so people may be counted
multiple times):
function countAncestors ( person , test ) {
function combine ( current , fromMother , fromFather ) {
var thisOneCounts = current != person && test ( current );
return fromMother + fromFather + ( thisOneCounts ? 1 : 0) ;
}
return reduceAncestors ( person , combine , 0) ;
}
function longLivingPercentage ( person ) {
var all = countAncestors ( person , function ( person ) {
return true ;
}) ;
var longLiving = countAncestors ( person , function ( person ) {
return ( person
...
born ) >= 70;
}) ;
return longLiving / all ;
}
console
...
129

Such numbers are not to be taken too seriously, given that our data set
contains a rather arbitrary collection of people
...


101

Binding
The bind method, which all functions have, creates a new function that
will call the original function but with some of the arguments already
fixed
...
It defines a function isInSet that tells us whether a person is in a given set of strings
...

var theSet = [" Carel Haverbeke ", " Maria van Brussel ",
" Donald Duck "];
function isInSet ( set , person ) {
return set
...
name ) > -1;
}
console
...
filter ( function ( person ) {
return isInSet ( theSet , person );
}) ) ;
// → [{ name : " Maria van Brussel ",
...
}]
console
...
filter ( isInSet
...
same result

The call to bind returns a function that will call isInSet with theSet as
first argument, followed by any remaining arguments given to the bound
function
...
I’ll describe this in more
detail in the next chapter
...
It allows us to write
computations with “gaps” in them as functions and have the code that
calls these functions fill in those gaps by providing function values that

102

describe the missing computations
...

Functions have an apply method that can be used to call them with an
array specifying their arguments
...


Exercises
Flattening
Use the reduce method in combination with the concat method to “flatten”
an array of arrays into a single array that has all the elements of the input
arrays
...
You can use the average function defined earlier in
this chapter
...
The byName object, which makes it easy to find a
person’s object from their name, might be useful here
...
Let’s take a
closer look at that phenomenon
...
A person is assigned to a century by taking their year
of death, dividing it by 100, and rounding it up, as in Math
...

died / 100)
...
It should accept as arguments an array and a function that
computes the group for an element in the array and returns an object
that maps group names to arrays of group members
...
Both take a
predicate function that, when called with an array element as argument,
returns true or false
...
Similarly, some returns
true as soon as the predicate returns true for any of the elements
...

Write two functions, every and some, that behave like these methods,
except that they take the array as their first argument rather than being
a method
...

You wanted a banana but what you got was a gorilla holding
the banana and the entire jungle
...
In my profession, objects are a way of life, the subject of holy wars, and a beloved
buzzword that still hasn’t quite lost its power
...
Let’s start with a
brief history of objects as a programming construct
...
One philosophy is that complexity can be made manageable
by separating it into small compartments that are isolated from each
other
...

An object is a hard shell that hides the gooey complexity inside it and
instead offers us a few knobs and connectors (such as methods) that
present an interface through which the object is to be used
...


105

As an example, you can imagine an object that provides an interface to
an area on your screen
...
You’d have a set of methods—for
example, drawCircle—and those are the only things you need to know in
order to use such an object
...
Suddenly, there was a large tribe of people
declaring that objects were the right way to program—and that anything
that did not involve objects was outdated nonsense
...
In some circles,
objects have a rather bad reputation nowadays
...
There are several useful concepts, most importantly that of
encapsulation (distinguishing between internal complexity and external
interface), that the object-oriented culture has popularized
...

This chapter describes JavaScript’s rather eccentric take on objects
and the way they relate to some classical object-oriented techniques
...
This is a simple
method:
var rabbit = {};
rabbit
...
log (" The rabbit says  " + line + "  ") ;
};
rabbit
...
") ;
// → The rabbit says  I  m alive
...
When a function is called as a method—looked up as a property and
immediately called, as in object
...

function speak ( line ) {
console
...
type + " rabbit says
line + "  ") ;
}
var whiteRabbit = { type : " white " , speak : speak };
var fatRabbit = { type : " fat ", speak : speak };

"

+

whiteRabbit
...
speak (" I could sure use a carrot right now
...


The code uses the this keyword to output the type of rabbit that is
speaking
...
This first argument is
in fact used to give a value to this
...
It also calls the function
it is a method of but takes its arguments normally, rather than as an
array
...

speak
...
call ({ type : " old "} , " Oh my
...


Prototypes
Watch closely
...
log ( empty
...
{}
console
...
toString () ) ;
// → [ object Object ]

I just pulled a property out of an empty object
...
I have simply been withholding information about
the way JavaScript objects work
...
A prototype is another object
that is used as a fallback source of properties
...

So who is the prototype of that empty object? It is the great ancestral
prototype, the entity behind almost all objects, Object
...

console
...
getPrototypeOf ({}) ==
Object
...
log ( Object
...
prototype ));
// → null

As you might expect, the Object
...

The prototype relations of JavaScript objects form a tree-shaped structure, and at the root of this structure sits Object
...
It provides a
few methods that show up in all objects, such as toString, which converts
an object to a string representation
...
prototype as their prototype,
but instead have another object, which provides its own default properties
...
prototype, and arrays derive from

108

Array
...

console
...
getPrototypeOf ( isNaN ) ==
Function
...
log ( Object
...
prototype ) ;
// → true

Such a prototype object will itself have a prototype, often Object
...

The Object
...
You can use Object
...

var protoRabbit = {
speak : function ( line ) {
console
...
type + " rabbit says
line + "  ") ;
}
};
var killerRabbit = Object
...
type = " killer ";
killerRabbit
...
An individual rabbit object, like the killer rabbit, contains
properties that apply only to itself—in this case its type—and derives
shared properties from its prototype
...
In JavaScript, calling a function with
the new keyword in front of it causes it to be treated as a constructor
...

An object created with new is said to be an instance of its constructor
...
It is a convention to capitalize
the names of constructors so that they are easily distinguished from other
functions
...
type = type ;
}
var killerRabbit = new Rabbit (" killer ") ;
var blackRabbit = new Rabbit (" black ") ;
console
...
type ) ;
// → black

Constructors (in fact, all functions) automatically get a property named
prototype, which by default holds a plain, empty object that derives from
Object
...
Every instance created with this constructor will have
this object as its prototype
...
prototype
...
log (" The " + this
...
speak (" Doom
...


"

+

It is important to note the distinction between the way a prototype
is associated with a constructor (through its prototype property) and
the way objects have a prototype (which can be retrieved with Object
...
The actual prototype of a constructor is Function
...
Its prototype property will be the prototype of instances created through it but is not its own prototype
...
If there is a property by the same
name in the prototype, this property will no longer affect the object
...


110

Rabbit
...
teeth = " small ";
console
...
teeth ) ;
// → small
killerRabbit
...
log ( killerRabbit
...
log ( blackRabbit
...
log ( Rabbit
...
teeth );
// → small

The following diagram sketches the situation after this code has run
...

Rabbit
prototype
Object

killerRabbit

create:
prototype

...
"
adjective: "killer"
teeth: "small"
speak:
toString:

...
As the rabbit teeth example shows, it can be used to express
exceptional properties in instances of a more generic class of objects,
while letting the nonexceptional objects simply take a standard value
from their prototype
...

console
...
prototype
...
prototype
...
log ([1 , 2]
...
join(",")
on it—it puts commas between the values in the array
...
That
function doesn’t know about arrays, so it simply puts the word “object”
and the name of the type between square brackets
...
prototype
...
log ( Object
...
toString
...
For example, it might become necessary for
our rabbits to dance
...
prototype
...
log (" The " + this
...
") ;
};
killerRabbit
...


That’s convenient
...

In previous chapters, we used an object as a way to associate values
with names by creating properties for the names and giving them the
corresponding value as their value
...
069) ;
storePhi (" touched tree " , -0
...
But
unfortunately, the object’s prototype gets in the way
...
prototype
...
log ( name ) ;
// → pizza

112

// → touched tree
// → nonsense
console
...
log (" toString " in map ) ;
// → true
// Delete the problematic property again
delete Object
...
nonsense ;

That’s all wrong
...

And there definitely is no event called “toString”
...
This is because JavaScript distinguishes between
enumerable and nonenumerable properties
...
The standard properties in Object
...

It is possible to define our own nonenumerable properties by using
the Object
...

Object
...
prototype , " hiddenNonsense ",
{ enumerable : false , value : " hi "}) ;
for ( var name in map )
console
...
log ( map
...
That’s
good
...
prototype properties exist in our object
...

console
...
hasOwnProperty (" toString ") );
// → false

This method tells us whether the object itself has the property, without
looking at its prototypes
...

When you are worried that someone (some other code you loaded into
your program) might have messed with the base object prototype, I
recommend you write your for/in loops like this:
for ( var name in map ) {
if ( map
...
this is an own property
}
}

Prototype-less objects
But the rabbit hole doesn’t end there
...
hasOwnProperty will try to call the local property, which holds
a number, not a function
...
We saw the Object
...

You are allowed to pass null as the prototype to create a fresh object
with no prototype
...

var map = Object
...
069;
console
...
log (" pizza " in map ) ;
// → true

Much better! We no longer need the hasOwnProperty kludge because all the
properties the object has are its own properties
...
prototype
...
I mentioned that some of the standard
prototypes define their own version of toString so they can create a string
that contains more useful information than "[object Object]"
...
When a piece of code
is written to work with objects that have a certain interface—in this
case, a toString method—any kind of object that happens to support
this interface can be plugged into the code, and it will just work
...
Polymorphic code can work with values of different shapes,
as long as they support the interface it expects
...
The project is this: we will
write a program that, given an array of arrays of table cells, builds up a
string that contains a nicely laid out table—meaning that the columns
are straight and the rows are aligned
...
The builder function will then ask the cells to draw themselves at

115

the correct size and assemble the results into a single string
...
That way, the types of cells that the program
supports is not fixed in advance
...

This is the interface:
• minHeight() returns a number indicating the minimum height this
cell requires (in lines)
...

• draw(width, height) returns an array of length height, which contains
a series of strings that are each width characters wide
...

I’m going to make heavy use of higher-order array methods in this example since it lends itself well to that approach
...
The rows variable will hold an
array of arrays, with each inner array representing a row of cells
...
map ( function ( row ) {
return row
...
max ( max , cell
...
map ( function (_ , i ) {
return rows
...
max ( max , row [ i ]
...

The rowHeights function shouldn’t be too hard to follow
...

Things are slightly harder for the colWidths function because the outer
array is an array of rows, not of columns
...
By mapping over the elements of the first row and only using
the mapping function’s second argument, colWidths builds up an array
with one element for every column index
...

Here’s the code to draw a table:
function drawTable ( rows ) {
var heights = rowHeights ( rows );
var widths = colWidths ( rows );
function drawLine ( blocks , lineNo ) {
return blocks
...
join (" ") ;
}
function drawRow ( row , rowNum ) {
var blocks = row
...
draw ( widths [ colNum ], heights [ rowNum ]) ;
}) ;
return blocks [0]
...
join ("\ n ") ;
}
return rows
...
join ("\ n ") ;
}

117

The drawTable function uses the internal helper function drawRow to draw
all rows and then joins them together with newline characters
...
A single cell containing simply the number 3776 might be
represented by a single-element array like ["3776"], whereas an underlined
cell might take up two lines and be represented by the array ["name",
"----"]
...
The second call to map in drawRow
builds up this output line by line by mapping over the lines in the
leftmost block and, for each of those, collecting a line that spans the full
width of the table
...

The function drawLine extracts lines that should appear next to each
other from an array of blocks and joins them with a space character to
create a one-character gap between the table’s columns
...
The constructor splits a string into
an array of lines using the string method split, which cuts up a string
at every occurrence of its argument and returns an array of the pieces
...

function repeat ( string , times ) {
var result = "";
for ( var i = 0; i < times ; i ++)
result += string ;
return result ;
}
function TextCell ( text ) {
this
...
split ("\ n ") ;
}
TextCell
...
minWidth = function () {
return this
...
reduce ( function ( width , line ) {
return Math
...
length );
} , 0) ;
};
TextCell
...
minHeight = function () {

118

return this
...
length ;
};
TextCell
...
draw = function ( width , height ) {
var result = [];
for ( var i = 0; i < height ; i ++) {
var line = this
...
push ( line + repeat (" ", width - line
...
The draw
method uses it to add “padding” to lines so that they all have the
required length
...

var rows = [];
for ( var i = 0; i < 5; i ++) {
var row = [];
for ( var j = 0; j < 5; j ++) {
if (( j + i ) % 2 == 0)
row
...
push ( new TextCell (" ") ) ;
}
rows
...
log ( drawTable ( rows )) ;
// → ##
##
##
//
##
##
//
##
##
##
//
##
##
//
##
##
##

It works! But since all cells have the same size, the table-layout code
doesn’t really do anything interesting
...
net/code#6)
...
No
problem—we simply write a cell type that handles underlining
...
inner = inner ;
}
UnderlinedCell
...
minWidth = function () {
return this
...
minWidth () ;
};
UnderlinedCell
...
minHeight = function () {
return this
...
minHeight () + 1;
};
UnderlinedCell
...
draw = function ( width , height ) {
return this
...
draw ( width , height - 1)

...
It reports its minimum size as
being the same as that of its inner cell (by calling through to that cell’s
minWidth and minHeight methods) but adds one to the height to account
for the space taken up by the underline
...

Having an underlining mechanism, we can now write a function that
builds up a grid of cells from our data set
...
keys ( data [0]) ;
var headers = keys
...
map ( function ( row ) {
return keys
...
concat ( body ) ;
}
console
...

etcetera

The standard Object
...
The top row of the table must contain underlined cells that
give the names of the columns
...

The resulting table resembles the example shown before, except that
it does not right-align the numbers in the height column
...


Getters and setters
When specifying an interface, it is possible to include properties that
are not methods
...
But that’d have required us to compute them in the
constructor, which adds code there that isn’t strictly relevant to constructing the object
...

This has led some people to adopt a principle of never including nonmethod properties in interfaces
...
This approach has the downside that you will
end up writing—and reading—a lot of additional methods
...
We can specify properties that, from the outside, look like
normal properties but secretly have methods associated with them
...
elements
...
log (" Ignoring attempt to set height to ", value );
}
};
console
...
height );
// → 3
pile
...
You can
also add such a property to an existing object, for example a prototype, using the Object
...

Object
...
prototype , " heightProp ", {
get : function () { return this
...
length ; }
}) ;
var cell = new TextCell (" no \ nway ") ;
console
...
heightProp );
// → 2
cell
...
log ( cell
...
When a getter but no setter is defined,
writing to the property is simply ignored
...
It helps readability to right-align columns of numbers
...

We could simply write a whole new constructor with all three methods
in its prototype
...


122

function RTextCell ( text ) {
TextCell
...
prototype = Object
...
prototype );
RTextCell
...
draw = function ( width , height ) {
var result = [];
for ( var i = 0; i < height ; i ++) {
var line = this
...
push ( repeat (" " , width - line
...
An RTextCell is now basically equivalent to a TextCell,
except that its draw method contains a different function
...
It allows us to build slightly different
data types from existing data types with relatively little work
...
Once
this constructor has been called, we can assume that all the fields that
the old object type is supposed to contain have been added
...
Finally, we can override some of these properties by adding
them to our new prototype
...

function dataTable ( data ) {
var keys = Object
...
map ( function ( name ) {
return new UnderlinedCell ( new TextCell ( name ));
}) ;
var body = data
...
map ( function ( name ) {
var value = row [ name ];
// This was changed :
if ( typeof value == " number ")
return new RTextCell ( String ( value ));

123

else
return new TextCell ( String ( value ));
}) ;
}) ;
return [ headers ]
...
log ( drawTable ( dataTable ( MOUNTAINS )));
// →
...
But while the latter two are now
generally regarded as wonderful ideas, inheritance is somewhat controversial
...
Whereas encapsulation and polymorphism
can be used to separate pieces of code from each other, reducing the
tangledness of the overall program, inheritance fundamentally ties types
together, creating more tangle
...
I am not
going to tell you to avoid inheritance entirely—I use it regularly in my
own programs
...
A preferable way to extend types is through composition,
such as how UnderlinedCell builds on another cell object by simply storing
it in a property and forwarding method calls to it in its own methods
...
For this, JavaScript provides a binary operator
called instanceof
...
log ( new RTextCell (" A ") instanceof RTextCell );
// → true
console
...
log ( new TextCell (" A ") instanceof RTextCell );

124

// → false
console
...
An RTextCell is an instance
of TextCell because RTextCell
...
prototype
...
Almost every
object is an instance of Object
...
They
have prototypes, which are other objects, and will act as if they have
properties they don’t have as long as the prototype has that property
...
prototype as their prototype
...

The new object’s prototype will be the object found in the prototype
property of the constructor function
...
The instanceof operator can, given an object and a constructor,
tell you whether that object is an instance of that constructor
...
The rest of the details that make up your object
are now encapsulated, hidden behind the interface
...
It is very useful
...
This gives you an object type similar to the old type but
for which you can add and override properties as you see fit
...
It takes x and y parameters (numbers), which it should save to
properties of the same name
...

Add a getter property length to the prototype that computes the length
of the vector—that is, the distance of the point (x, y) from the origin (0,
0)
...
It should
wrap another cell (like UnderlinedCell does) and ensure that the resulting
cell has at least the given width and height, even if the inner cell would
naturally be smaller
...

An object that provides this interface represents a sequence, and the
interface must somehow make it possible for code that uses such an
object to iterate over the sequence, looking at the element values it is
made up of and having some way to find out when the end of the sequence
is reached
...
log on its first five elements—
or fewer, if the sequence has fewer than five elements
...
Implement
another object type RangeSeq that iterates over a range of integers (taking

126

from

and to arguments to its constructor) instead
...

—Edsger Dijkstra, The Threats to Computing Science

7 Project: Electronic Life
In “project” chapters, I’ll stop pummeling you with new theory for a
brief moment and instead work through a program with you
...

Our project in this chapter is to build a virtual ecosystem, a little world
populated with critters that move around and struggle for survival
...
Namely, a world will be a two-dimensional grid where each
entity takes up one full square of the grid
...

Thus, we chop both time and space into units with a fixed size: squares
for space and turns for time
...
But our simulation is intended to be amusing,
not accurate, so we can freely cut such corners
...

var plan = ["############################" ,
"#
#
#
o
##" ,
"#
#" ,
"#
#####
#" ,
"##
#
#
##
#" ,
"###
##
#
#" ,
"#
###
#
#" ,
"#
####
#" ,
"#
##
o
#" ,
"# o #
o
### #" ,
"#
#
#" ,

128

"############################"];

The “#” characters in this plan represent walls and rocks, and the “o”
characters represent critters
...

A plan array can be used to create a world object
...
It has a toString method, which
converts the world back to a printable string (similar to the plan it was
based on) so that we can see what’s going on inside
...


Representing space
The grid that models the world has a fixed width and height
...
We use a simple type, Vector
(as seen in the exercises for the previous chapter), to represent these
coordinate pairs
...
x = x;
this
...
prototype
...
x + other
...
y + other
...
A grid is part
of a world, but we are making it a separate object (which will be a
property of a world object) to keep the world object itself simple
...

To store a grid of values, we have several options
...
log ( grid [1][2]) ;

129

//



bottom right

Or we can use a single array, with size width × height, and decide that
the element at (x,y) is found at position x + (y × width) in the array
...
log ( grid [2 + (1 * 3) ]) ;
// → bottom right

Since the actual access to this array will be wrapped in methods on
the grid object type, it doesn’t matter to outside code which approach
we take
...
When calling the Array constructor with a
single number as an argument, it creates a new empty array of the given
length
...
space = new Array ( width * height );
this
...
height = height ;
}
Grid
...
isInside = function ( vector ) {
return vector
...
x < this
...
y >= 0 && vector
...
height ;
};
Grid
...
get = function ( vector ) {
return this
...
x + this
...
y ];
};
Grid
...
set = function ( vector , value ) {
this
...
x + this
...
y] = value ;
};

And here is a trivial test:
var grid = new Grid (5 , 5) ;
console
...
get ( new Vector (1 , 1) ));
// → undefined
grid
...
log ( grid
...
I mentioned that the
world will ask the critters what actions they want to take
...
An action is an object with a type property, which names the
type of action the critter wants to take, for example "move"
...

Critters are terribly myopic and can see only the squares directly
around them on the grid
...
When the act method is called, it
is given a view object that allows the critter to inspect its surroundings
...
Here’s the object we will use to
map from direction names to coordinate offsets:
var directions = {
" n ": new Vector ( 0 , -1) ,
" ne ": new Vector ( 1 , -1) ,
" e ": new Vector ( 1 , 0) ,
" se ": new Vector ( 1 , 1) ,
" s ": new Vector ( 0 , 1) ,
" sw ": new Vector ( -1 , 1) ,
" w ": new Vector ( -1 , 0) ,
" nw ": new Vector ( -1 , -1)
};

The view object has a method look, which takes a direction and returns
a character, for example "\#" when there is a wall in that direction, or
" " (space) when there is nothing there
...
Both take a map character as an
argument
...
The
second returns an array containing all directions with that character
...


131

Here is a simple, stupid critter that just follows its nose until it hits
an obstacle and then bounces off in a random open direction:
function randomElement ( array ) {
return array [ Math
...
random () * array
...
split (" ") ;
function BouncingCritter () {
this
...
prototype
...
look ( this
...
direction = view
...
direction };
};

The randomElement helper function simply picks a random element from an
array, using Math
...
We’ll
use this again later because randomness can be useful in simulations
...
We could also have used Object
...

In most situations, modern JavaScript engines will return properties in
the order they were defined, but they are not required to
...
direction from
getting the value null if the critter is somehow trapped with no empty
space around it (for example when crowded into a corner by other critters)
...
The constructor takes a plan
(the array of strings representing the world’s grid, described earlier)
and a legend as arguments
...
It contains a constructor for every

132

character—except for the space character, which always refers to null,
the value we’ll use to represent empty space
...
originChar = ch ;
return element ;
}
function World ( map , legend ) {
var grid = new Grid ( map [0]
...
length );
this
...
legend = legend ;
map
...
length ; x ++)
grid
...
Then we add an
originChar property to it to make it easy to find out what character the
element was originally created from
...
This method builds up a maplike string from the world’s current state by performing a two-dimensional loop over the squares on the
grid
...
originChar ;
}
World
...
toString = function () {
var output = "";
for ( var y = 0; y < this
...
height ; y ++) {

133

for ( var x = 0; x < this
...
width ; x ++) {
var element = this
...
get ( new Vector (x , y));
output += charFromElement ( element );
}
output += "\ n ";
}
return output ;
};

A wall is a simple object—it is used only for taking up space and has no
act method
...

var world = new World ( plan , {"#": Wall ,
"o ": BouncingCritter }) ;
console
...
toString () ) ;
// → ############################
//
#
#
#
o
##
//
#
#
//
#
#####
#
//
##
#
#
##
#
//
###
##
#
#
//
#
###
#
#
//
#
####
#
//
#
##
o
#
//
# o #
o
### #
//
#
#
#
//
############################

this and its scope
The World constructor contains a call to forEach
...
Each function call gets
its own this binding, so the this in the inner function does not refer to

134

the newly constructed object that the outer this refers to
...

This means that we can’t write this
...
Instead, the outer function creates a normal local variable,
grid, through which the inner function gets access to the grid
...
Fortunately, the next
version of the language provides a solution for this problem
...
A common pattern is to say var self = this and
from then on refer to self, which is a normal variable and thus visible to
inner functions
...

var test = {
prop : 10 ,
addPropTo : function ( array ) {
return array
...
prop + elt ;
}
...
log ( test
...

Most standard higher-order methods on arrays, such as forEach and map,
take an optional second argument that can also be used to provide a this
for the calls to the iteration function
...

var test = {
prop : 10 ,
addPropTo : function ( array ) {
return array
...
prop + elt ;
}, this ) ; // ← no bind
}
};

135

console
...
addPropTo ([5]) ) ;
// → [15]

This works only for higher-order functions that support such a context
parameter
...

In our own higher-order functions, we can support such a context parameter by using the call method to call the function given as an argument
...
prototype
...
height ; y ++) {
for ( var x = 0; x < this
...
space [ x + y * this
...
call ( context , value , new Vector (x , y));
}
}
};

Animating life
The next step is to write a turn method for the world object that gives
the critters a chance to act
...
When
it finds one, turn calls that method to get an action object and carries out
the action when it is valid
...

There is one potential problem with this approach
...
Thus, we have to keep an array of critters that
have already had their turn and ignore them when we see them again
...
prototype
...
grid
...
act && acted
...
push ( critter ) ;

136

this
...
The letAct method
contains the actual logic that allows the critters to move
...
prototype
...
act ( new View ( this , vector ));
if ( action && action
...
checkDestination ( action , vector );
if ( dest && this
...
get ( dest ) == null ) {
this
...
set ( vector , null ) ;
this
...
set ( dest , critter );
}
}
};
World
...
checkDestination = function ( action , vector ) {
if ( directions
...
direction )) {
var dest = vector
...
direction ]) ;
if ( this
...
isInside ( dest ))
return dest ;
}
};

First, we simply ask the critter to act, passing it a view object that
knows about the world and the critter’s current position in that world
(we’ll define View in a moment)
...

If the action’s type is not "move", it is ignored
...

Note that letAct takes care to ignore nonsense input—it doesn’t assume
that the action’s direction property is valid or that the type property
makes sense
...
The main reason for doing it is to validate inputs coming
from sources you don’t control (such as user or file input), but it can

137

also be useful to isolate subsystems from each other
...
They can
just request an action, and the world will figure out whether to allow it
...
They are an internal detail
...
JavaScript does
not, so you will have to rely on some other form of communication to
describe what is part of an object’s interface
...
This will make accidental uses of properties that are not
part of an object’s interface easier to spot
...
world = world ;
this
...
prototype
...
vector
...
world
...
isInside ( target ))
return charFromElement ( this
...
grid
...
prototype
...
look ( dir ) == ch )
found
...
prototype
...
findAll ( ch );
if ( found
...
For coordinates outside the grid, look simply
pretends that there is a wall there so that if you define a world that isn’t
walled in, the critters still won’t be tempted to try to walk off the edges
...
Now that we’ve added all the
necessary methods, it should be possible to actually make the world
move
...
turn () ;
console
...
toString () );
}
// →
...
net
...
Can you think of another interesting form
of behavior?
The one I came up with is a critter that moves along walls
...
This turns out to be not entirely trivial to implement
...
Since directions are modeled by a set of strings, we need to define our own operation
(dirPlus) to calculate relative directions
...
Similarly, dirPlus("s", -2)
means 90 degrees counterclockwise from south, which is east
...
indexOf ( dir );
return directionNames [( index + n + 8) % 8];
}
function WallFollower () {
this
...
prototype
...
dir ;
if ( view
...
dir , -3) ) != " ")
start = this
...
dir , -2) ;
while ( view
...
dir ) != " ") {
this
...
dir , 1) ;
if ( this
...
dir };
};

The act method only has to “scan” the critter’s surroundings, starting
from its left side and going clockwise until it finds an empty square
...

What complicates things is that a critter may end up in the middle of
empty space, either as its start position or as a result of walking around
another critter
...

So there is an extra check (the if statement) to start scanning to the
left only if it looks like the critter has just passed some kind of obstacle—
that is, if the space behind and to the left of the critter is not empty
...

And finally, there’s a test comparing this
...


A more lifelike simulation
To make life in our world more interesting, we will add the concepts
of food and reproduction
...
When the critter has enough energy, it can reproduce,
generating a new critter of the same kind
...

If critters only move around and eat one another, the world will soon
succumb to the law of increasing entropy, run out of energy, and become
a lifeless wasteland
...
Plants do not move
...

To make this work, we’ll need a world with a different letAct method
...

One solution is to use inheritance
...
The new letAct method delegates the work
of actually performing an action to various functions stored in the actionTypes
object
...
call ( this , map , legend );

141

}
LifelikeWorld
...
create ( World
...
create ( null );
LifelikeWorld
...
letAct = function ( critter , vector ) {
var action = critter
...
type in actionTypes &&
actionTypes [ action
...
call ( this , critter ,
vector , action );
if (! handled ) {
critter
...
2;
if ( critter
...
grid
...
Note the use of call to give the handler access to
the world, through its this binding
...
It loses one-fifth point of energy, and if its
energy level drops to zero or below, the creature dies and is removed
from the grid
...

When an action object like {type: "grow"} is returned, the following handler method will be called:
actionTypes
...
energy += 0
...

Moving is more involved
...
move = function ( critter , vector , action ) {
var dest = this
...
energy <= 1 ||
this
...
get ( dest ) != null )
return false ;
critter
...
grid
...
grid
...
If not, or if the
destination isn’t empty, or if the critter lacks the required energy, move
returns false to indicate no action was taken
...

In addition to moving, critters can eat
...
eat = function ( critter , vector , action ) {
var dest = this
...
grid
...
energy == null )
return false ;
critter
...
energy ;
this
...
set ( dest , null ) ;
return true ;
};

Eating another critter also involves providing a valid destination square
...
If
so, the energy from the eaten is transferred to the eater, and the victim
is removed from the grid
...

actionTypes
...
legend ,
critter
...
checkDestination ( action , vector );
if ( dest == null ||
critter
...
energy ||
this
...
get ( dest ) != null )
return false ;
critter
...
energy ;
this
...
set ( dest , baby ) ;
return true ;
};

Reproducing costs twice the energy level of the newborn critter
...
Once we have a baby, we can find its energy level
and test whether the parent has enough energy to successfully bring it
into the world
...

If everything is okay, the baby is put onto the grid (it is now no longer
hypothetical), and the energy is spent
...
We
could put the critters from the old world into it, but they would just die
since they don’t have an energy property
...
First
we’ll write a plant, which is a rather simple life-form
...
energy = 3 + Math
...
prototype
...
energy > 15) {
var space = view
...
energy < 20)
return { type : " grow "};
};

144

Plants start with an energy level between 3 and 7, randomized so that
they don’t all reproduce in the same turn
...
If a plant can’t reproduce, it simply grows until it reaches
energy level 20
...

function PlantEater () {
this
...
prototype
...
find (" ") ;
if ( this
...
find ("*") ;
if ( plant )
return { type : " eat " , direction : plant };
if ( space )
return { type : " move " , direction : space };
};

We’ll use the * character for plants, so that’s what this creature will look
for when it searches for food
...
Imagine the
following map as a grassy valley with a herd of herbivores in it, some
boulders, and lush plant life everywhere
...
These snapshots illustrate a
typical run of this world
...
Sometimes, the ecosystem recovers
and another cycle starts
...
If it’s the herbivores, the whole space will fill with plants
...
Ah, the cruelty of nature
...
To deal with this, we could try to create a smarter
plant eater
...
First, they
are terribly greedy, stuffing themselves with every plant they see until
they have wiped out the local plant life
...
find method returns a random direction when
multiple directions match) causes them to stumble around ineffectively
and starve if there don’t happen to be any plants nearby
...

Write a new critter type that tries to address one or more of these
points and substitute it for the old PlantEater type in the valley world
...
Tweak it some more if necessary
...
Write
another critter that survives by eating the herbivore critter
...
Try to find a strategy to make the ecosystem run
smoothly for at least a little while
...
This way, local
population booms or busts are less likely to wipe out a species entirely,
and there is space for the relatively large prey population needed to
sustain a small predator population
...
Therefore, if you write the code as cleverly as possible,
you are, by definition, not smart enough to debug it
...
J
...
Sometimes those thoughts are confused
...
Either way, the result is a flawed program
...
Bugs can be programmer
errors or problems in other systems that the program interacts with
...

Often, problems surface only when a program encounters a situation
that the programmer didn’t originally consider
...
When the user is asked to input their age and
types orange, this puts our program in a difficult position
...


Programmer mistakes
When it comes to programmer mistakes, our aim is simple
...
Such mistakes can range from simple typos that
cause the computer to complain as soon as it lays eyes on our program to
subtle mistakes in our understanding of the way the program operates,
causing incorrect outcomes only in specific situations
...

The degree to which languages help you find such mistakes varies
...
Some languages want to know the types of all your variables and
expressions before even running a program and will tell you right away
when a type is used in an inconsistent way
...


149

There are some things that JavaScript does complain about, though
...
Other things, such as calling something that’s not a function
or looking up a property on an undefined value, will cause an error to be
reported when the program is running and encounters the nonsensical
action
...
And the program happily continues, convinced that it’s doing something meaningful
...
It might not trigger an error at all but silently cause the program’s
output to be wrong
...

The process of finding mistakes—bugs—in programs is called debugging
...
This
is done by putting the string "use strict" at the top of a file or a function
body
...
log (" Happy happy ") ;
}
canYouSpotTheProblem () ;
// → ReferenceError : counter is not defined

Normally, when you forget to put var in front of your variable, as with
counter in the example, JavaScript quietly creates a global variable and
uses that
...
This is
very helpful
...

Another change in strict mode is that the this binding holds the value
undefined in functions that are not called as methods
...
So if
you accidentally call a method or constructor incorrectly in strict mode,
JavaScript will produce an error as soon as it tries to read something
from this, rather than happily working with the global object, creating
and reading global variables
...
name = name ; }
var ferdinand = Person (" Ferdinand ") ; // oops
console
...
In strict mode, the result is different
...
name = name ; }
// Oops , forgot  new 
var ferdinand = Person (" Ferdinand ") ;
// → TypeError : Cannot set property  name  of undefined

We are immediately told that something is wrong
...

Strict mode does a few more things
...

In short, putting a "use strict" at the top of your program rarely hurts
and might help you spot a problem
...

Doing this by hand, again and again, is a sure way to drive yourself
insane
...


151

As an example, we once again use the Vector type
...
x = x;
this
...
prototype
...
x + other
...
y + other
...
Then, every time we change the implementation, we follow
up by running the test program so that we can be reasonably confident
that we didn’t break anything
...

function
var p1
var p2
var p3

testVector () {
= new Vector (10 , 20) ;
= new Vector ( -10 , 5) ;
= p1
...
x !== 10) return " fail : x property ";
if ( p1
...
x !== -10) return " fail : negative x property ";
if ( p3
...
y !== 25) return " fail : y from plus ";
return " everything ok ";
}
console
...

Fortunately, there exist pieces of software that help you build and run
collections of tests (test suites) by providing a language (in the form
of functions and methods) suited to expressing tests and by outputting
informative information when a test fails
...


152

Debugging
Once you notice that there is something wrong with your program because it misbehaves or produces errors, the next step is to figure out
what the problem is
...
The error message will point at a specific line
of your program, and if you look at the error description and that line
of code, you can often see the problem
...
Sometimes the line that triggered the problem is
simply the first place where a bogus value produced elsewhere gets used
in an invalid way
...
If you have been solving the exercises in the earlier
chapters, you will probably have already experienced such situations
...
But
the insane output that it currently produces suggests that it has a bug
...
log ( numberToString (13 , 10) ) ;
// → 1
...
3 e -3221
...
3 e -3201
...
3 e
...
3

Even if you see the problem already, pretend for a moment that you
don’t
...

This is where you must resist the urge to start making random changes
to the code
...
Analyze what is happening and come up
with a theory of why it might be happening
...

Putting a few strategic console
...
In this
case, we want n to take the values 13, 1, and then 0
...

13
1
...
13
0
...

1
...
Dividing 13 by 10 does not produce a whole number
...
floor(n / base) so that the
number is properly “shifted” to the right
...
log is to use the debugger capabilities of
your browser
...
This will cause the execution of the
program to pause every time the line with the breakpoint is reached
and allow you to inspect the values of variables at that point
...
Another way to set a breakpoint is to include a debugger
statement (consisting of simply that keyword) in your program
...


Error propagation
Not all problems can be prevented by the programmer, unfortunately
...

Simple programs, or programs that run only under your supervision,
can afford to just give up when such a problem occurs
...
“Real” applications, on the other hand, are
expected to not simply crash
...
In other cases, it is better
to report to the user what went wrong and then give up
...

Say you have a function promptInteger that asks the user for a whole
number and returns it
...
Common choices for
such values are null and undefined
...
log ( promptNumber (" How many trees do you see ?") );

This is a sound strategy
...
Or it
could again return a special value to its caller to indicate that it failed
to do what it was asked
...
It does, however, have its
downsides
...

The second issue with returning special values is that it can lead to
some very cluttered code
...
And if its response
to finding null is to simply return null itself, the caller will in turn have
to check for it, and so on
...
This is what exception handling does
...

Raising an exception somewhat resembles a super-charged return from
a function: it jumps out of not just the current function but also out
of its callers, all the way down to the first call that started the current
execution
...
You may remember the
stack of function calls that was mentioned in Chapter 3
...

If exceptions always zoomed right down to the bottom of the stack,
they would not be of much use
...
Their power lies in the fact that you can set
“obstacles” along the stack to catch the exception as it is zooming down
...

Here’s an example:
function promptDirection ( question ) {
var result = prompt ( question , "") ;
if ( result
...
toLowerCase () == " right ") return "R ";
throw new Error (" Invalid direction : " + result );
}
function look () {
if ( promptDirection (" Which way ?") == "L ")
return " a house ";
else
return " two angry bears ";
}
try {
console
...
log (" Something went wrong : " + error );
}

156

The throw keyword is used to raise an exception
...

When the code in the try block causes an exception to be raised, the
catch block is evaluated
...
After the catch block finishes—or
if the try block finishes without problems—control proceeds beneath the
entire try/catch statement
...
This is a standard JavaScript constructor that creates an object
with a message property
...
This information
is stored in the stack property and can be helpful when trying to debug
a problem: it tells us the precise function where the problem occurred
and which other functions led up to the call that failed
...
This is the big advantage of exceptions—
error-handling code is necessary only at the point where the error occurs
and at the point where it is handled
...

Well, almost…

Cleaning up after exceptions
Consider the following situation: a function, withContext, wants to make
sure that, during its execution, the top-level variable context holds a
specific context value
...

var context = null ;
function withContext ( newContext , body ) {
var oldContext = context ;
context = newContext ;
var result = body () ;
context = oldContext ;
return result ;
}

157

What if body raises an exception? In that case, the call to withContext will
be thrown off the stack by the exception, and context will never be set
back to its old value
...
They may be
followed by a finally block either instead of or in addition to a catch
block
...
If a function has to clean
something up, the cleanup code should usually be put into a finally
block
...
Even if we return directly from the try block,
the finally block will be run
...
log (" Ignoring : " + e );
}
// → Ignoring : Error : Not enough context !
console
...


158

Selective catching
When an exception makes it all the way to the bottom of the stack
without being caught, it gets handled by the environment
...
In browsers, a description of the
error typically gets written to the JavaScript console (reachable through
the browser’s Tools or Developer menu)
...
An unhandled exception is a reasonable way to signal a broken program, and the
JavaScript console will, on modern browsers, provide you with some information about which function calls were on the stack when the problem
occurred
...

Invalid uses of the language, such as referencing a nonexistent variable,
looking up a property on null, or calling something that’s not a function,
will also result in exceptions being raised
...

When a catch body is entered, all we know is that something in our try
body caused an exception
...

JavaScript (in a rather glaring omission) doesn’t provide direct support
for selectively catching exceptions: either you catch them all or you don’t
catch any
...

But it might not be
...

Here is an example, which attempts to keep on calling promptDirection
until it gets a valid answer:
for (;;) {
try {
var dir = promtDirection (" Where ?") ; // ← typo !
console
...
log (" Not a valid direction
...
") ;

159

}
}

The for (;;) construct is a way to intentionally create a loop that doesn’t
terminate on its own
...
But we misspelled promptDirection, which will result
in an “undefined variable” error
...
Not only
does this cause an infinite loop, but it also “buries” the useful error
message about the misspelled variable
...
And even then, think
carefully about how you might be hiding information
...
We can do this by
checking in the catch block whether the exception we got is the one we are
interested in and by rethrowing it otherwise
...
But that’s a shaky way to write code—we’d
be using information that’s intended for human consumption (the message) to make a programmatic decision
...

Rather, let’s define a new type of error and use instanceof to identify
it
...
message = message ;
this
...
stack ;
}
InputError
...
create ( Error
...
prototype
...
prototype so that instanceof
Error will also return true for InputError objects
...

The assignment to the stack property tries to give this object a some-

160

what useful stack trace, on platforms that support it, by creating a
regular error object and then using that object’s stack property as its
own
...

function promptDirection ( question ) {
var result = prompt ( question , "") ;
if ( result
...
toLowerCase () == " right ") return "R ";
throw new InputError (" Invalid direction : " + result );
}

And the loop can catch it more carefully
...
log (" You chose " , dir );
break ;
} catch ( e ) {
if ( e instanceof InputError )
console
...
Try again
...
If you reintroduce the typo, the undefined variable error will
be properly reported
...

Consider this helper function, assert:
function AssertionFailed ( message ) {
this
...
prototype = Object
...
prototype );

161

function assert ( test , message ) {
if (! test )
throw new AssertionFailed ( message );
}
function lastElement ( array ) {
assert ( array
...
length - 1];
}

This provides a compact way to enforce expectations, helpfully blowing
up the program if the stated condition does not hold
...
Fetching
the last element from an empty array does not make much sense, so it
is almost certainly a programmer error to do so
...


Summary
Mistakes and bad input are facts of life
...
They can become easier to notice by having automated
test suites and adding assertions to your programs
...
Sometimes, when the problem can be handled
locally, special return values are a sane way to track them
...

Throwing an exception causes the call stack to be unwound until the
next enclosing try/catch block or until the bottom of the stack
...
To deal with the unpredictable control flow caused
by exceptions, finally blocks can be used to ensure a piece of code is
always run when a block finishes
...
Write a function that wraps this clunky
function and just keeps trying until a call succeeds, after which it returns
the result
...


The locked box
Consider the following (rather contrived) object:
var box = {
locked : true ,
unlock : function () { this
...
locked = true ; },
_content : [] ,
get content () {
if ( this
...
_content ;
}
};

It is a box with a lock
...
Directly accessing the _content property is not
allowed
...


163

“Some people, when confronted with a problem, think ‘I know,
I’ll use regular expressions
...

—Jamie Zawinski

9 Regular Expressions
Programming tools and techniques survive and spread in a chaotic, evolutionary way
...

In this chapter, I will discuss one such tool, regular expressions
...
They form
a small, separate language that is part of JavaScript and many other
languages and tools
...

Their syntax is cryptic, and the programming interface JavaScript provides for them is clumsy
...
Properly understanding regular expressions will
make you a more effective programmer
...
It can either be constructed
with the RegExp constructor or written as a literal value by enclosing the
pattern in forward slash (/) characters
...

When using the RegExp constructor, the pattern is written as a normal
string, so the usual rules apply for backslashes
...
First, since a forward
slash ends the pattern, we need to put a backslash before any forward

164

slash that we want to be part of the pattern
...
Some characters, such as question marks and plus signs,
have special meanings in regular expressions and must be preceded by a
backslash if they are meant to represent the character itself
...
For the time being, this may not be realistic, so when
in doubt, just put a backslash before any character that is not a letter,
number, or whitespace
...
The simplest one
is test
...

console
...
test (" abcde ") );
// → true
console
...
test (" abxde ") );
// → false

A regular expression consisting of only nonspecial characters simply represents that sequence of characters
...


Matching a set of characters
Finding out whether a string contains abc could just as well be done
with a call to indexOf
...

Say we want to match any number
...


165

Both of the following expressions match all strings that contain a digit:
console
...
test (" in 1992") );
// → true
console
...
test (" in 1992") );
// → true

Within square brackets, a dash (-) between two characters can be used
to indicate a range of characters, where the ordering is determined by
the character’s Unicode number
...

There are a number of common character groups that have their own
built-in shortcuts
...

\d Any digit character
\w An alphanumeric character (“word character”)
\s Any whitespace character (space, tab, newline, and similar)
\D A character that is not a digit
\W A nonalphanumeric character
\S A nonwhitespace character

...
log ( dateTime
...
log ( dateTime
...
We’ll see a slightly improved version of this
expression later
...
For
example, [\d
...
But note that
the period itself, when used between square brackets, loses its special
meaning
...

To invert a set of characters—that is, to express that you want to

166

match any character except the ones in the set—you can write a caret
(^) character after the opening bracket
...
log ( notBinary
...
log ( notBinary
...
What if we want to match a
whole number—a sequence of one or more digits?
When you put a plus sign (+) after something in a regular expression,
it indicates that the element may be repeated more than once
...

console
...
test ( "  1 2 3  " ) );
// → true
console
...
test ( "   " ) );
// → false
console
...
test ( "  1 2 3  " ) );
// → true
console
...
test ( "   " ) );
// → true

The star (*) has a similar meaning but also allows the pattern to match
zero times
...

A question mark makes a part of a pattern “optional”, meaning it may
occur zero or one time
...

var neighbor = / neighbou ?r /;
console
...
test (" neighbour ") );
// → true
console
...
test (" neighbor ") );
// → true

167

To indicate that a pattern should occur a precise number of times, use
curly braces
...
It is also possible to specify a range this way:
{2,4} means the element must occur at least twice and at most four times
...
It is also slightly more
readable
...
log ( dateTime
...
So {5,} means five or more times
...
A part of a regular expression that is enclosed in
parentheses counts as a single element as far as the operators following
it are concerned
...
log ( cartoonCrying
...
The third + applies to the whole group (hoo+), matching
one or more sequences like that
...


Matches and groups
The test method is the absolute simplest way to match a regular expression
...
Regular
expressions also have an exec (execute) method that will return null if

168

no match was found and return an object with information about the
match otherwise
...
exec (" one two 100") ;
console
...
log ( match
...
Other than that, the object
looks like (and in fact is) an array of strings, whose first element is the
string that was matched—in the previous example, this is the sequence
of digits that we were looking for
...

console
...
match (/\ d +/) );
// → ["100"]

When the regular expression contains subexpressions grouped with parentheses, the text that matched those groups will also show up in the array
...
The next element is the part
matched by the first group (the one whose opening parenthesis comes
first in the expression), then the second group, and so on
...
log ( quotedText
...
Similarly, when a group is matched multiple times, only the
last match ends up in the array
...
log (/ bad ( ly ) ?/
...
log (/(\ d ) +/
...
If we don’t just
want to verify whether a string contains a date but also extract it and
construct an object that represents it, we can wrap parentheses around

169

the digit patterns and directly pick the date out of the result of exec
...


The date type
JavaScript has a standard object type for representing dates—or rather,
points in time
...
If you simply create a date object using
new, you get the current date and time
...
log ( new Date () ) ;
// → Wed Dec 04 2013 14:24:57 GMT +0100 ( CET )

You can also create an object for a specific time
...
log ( new
// → Wed Dec 09
console
...
This is confusing and
silly
...

The last four arguments (hours, minutes, seconds, and milliseconds)
are optional and taken to be zero when not given
...
The
getTime method on a date object returns this number
...

console
...
getTime () );
// → 1387407600000
console
...
You can get the current millisecond
count by creating a new Date object and calling getTime on it but also by
calling the Date
...


170

Date objects provide methods like getFullYear, getMonth, getDate, getHours
, getMinutes, and getSeconds to extract their components
...

Putting parentheses around the parts of the expression that we are
interested in, we can now easily create a date object from a string
...
exec ( string ) ;
return new Date ( Number ( match [3]) ,
Number ( match [2]) - 1,
Number ( match [1]) );
}
console
...
A match may happen anywhere in
the string, so in this case, it’ll just start at the second character and end
at the second-to-last character
...
The caret matches the start of the input
string, while the dollar sign matches the end
...

If, on the other hand, we just want to make sure the date starts and
ends on a word boundary, we can use the marker \b
...

console
...
test (" concatenate ") );
// → true
console
...
test (" concatenate ") );

171

//



false

Note that a boundary marker doesn’t represent an actual character
...


Choice patterns
Say we want to know whether a piece of text contains not only a number
but a number followed by one of the words pig, cow, or chicken, or any
of their plural forms
...
The pipe character (|) denotes a choice between
the pattern to its left and the pattern to its right
...
log ( animalCount
...
log ( animalCount
...


The mechanics of matching
Regular expressions can be thought of as flow diagrams
...
We keep a current position in the string,
and every time we move through a box, we verify that the part of the
string after our current position matches that box
...

• Still at position 4, we find a digit, so we can also move past the
second box
...
There is a space here, not a digit, so we must take
the second path
...
We don’t see “cow” or “chicken” here, but
we do see “pig”, so we take that branch
...
There is an s character here, not a word boundary,
so we go through the s box
...
The end of a string counts as a word boundary,
so we go through the last box and have successfully matched this
string
...

In this case, there is a word boundary there, so it’d get past the first
box—but there is no digit, so it’d fail at the second box
...


173

Backtracking
The regular expression /\b([01]+b|\d+|[\da-f]+h)\b/ matches either a binary number followed by a b, a regular decimal number with no suffix
character, or a hexadecimal number (that is, base 16, with the letters
a to f standing for the digits 10 to 15) followed by an h
...
When matching the string "103", for example, it becomes clear only at the 3 that we are in the wrong branch
...

So the matcher backtracks
...
For the string "103", after
encountering the 3 character, it will start trying the branch for decimal
numbers
...

The matcher stops as soon as it finds a full match
...

Backtracking also happens for repetition operators like + and *
...
*x/ against "abcxe", the
...
The engine will then realize that it needs an x to match
the pattern
...
But the matcher doesn’t find
an x after abcx either, so it backtracks again, matching the star operator
to just abc
...

It is possible to write regular expressions that will do a lot of backtracking
...
For example, if we get confused while
writing a binary-number regular expression, we might accidentally write
something like /([01]+)+b/
...
Then it notices there is no b, so it backtracks one position,
goes through the outer loop once, and gives up again, trying to backtrack
out of the inner loop once more
...
This means the amount of work doubles
with each additional character
...


175

The replace method
String values have a replace method, which can be used to replace part
of the string with another string
...
log (" papa "
...
When a g option (for
global) is added to the regular expression, all matches in the string will
be replaced, not just the first
...
log (" Borobudur "
...
log (" Borobudur "
...
But for some unfortunate
reason, the choice relies on a property of the regular expression instead
...

For example, say we have a big string containing the names of people,
one name per line, in the format Lastname, Firstname
...
log (
" Hopper , Grace \ nMcCarthy , John \ nRitchie , Dennis "

...
$1 is replaced by the text that matched against the first
group, $2 by the second, and so on, up to $9
...


176

It is also possible to pass a function, rather than a string, as the second
argument to replace
...

Here’s a simple example:
var s = " the cia and fbi ";
console
...
replace (/\ b( fbi | cia )\ b/g , function ( str ) {
return str
...
slice (0 , unit
...
log ( stock
...

The (\d+) group ends up as the amount argument to the function, and
the (\w+) group gets bound to unit
...


Greed
It isn’t hard to use replace to write a function that removes all comments
from a piece of JavaScript code
...
replace (/\/\/
...
log ( stripComments ("1 + /* 2 */3") );
// → 1 + 3
console
...
log ( stripComments ("1 /* a */+/* b */ 1") );
// → 1 1

The part before the or operator simply matches two slash characters
followed by any number of non-newline characters
...
We use [^] (any character that is not in the
empty set of characters) as a way to match any character
...

But the output of the previous example appears to have gone wrong
...
If that causes the next part
of the pattern to fail, the matcher moves back one character and tries
again from there
...
It will find an
occurrence of */ after going back four characters and match that
...

Because of this behavior, we say the repetition operators (+, *, ?, and
{}) are greedy, meaning they match as much as they can and backtrack
from there
...

And that is exactly what we want in this case
...

function stripComments ( code ) {
return code
...
*|\/\*[^]*?\*\// g , "") ;
}
console
...
When using a repetition operator, consider the nongreedy variant
first
...
Say you want to
look for the user’s name in a piece of text and enclose it in underscore
characters to make it stand out
...

But you can build up a string and use the RegExp constructor on that
...
";
var regexp = new RegExp ("\\ b (" + name + ") \\ b", " gi ") ;
console
...
replace ( regexp , " _$1_ ") );
// → _Harry_ is a suspicious character
...
The second argument to the RegExp constructor contains
the options for the regular expression—in this case "gi" for global and
case-insensitive
...

To work around this, we can add backslashes before any character that
we don’t trust
...
But escaping
everything that’s not alphanumeric or whitespace is safe
...
";
var escaped = name
...
log ( text
...


The search method
The indexOf method on strings cannot be called with a regular expression
...
Like indexOf, it returns the first index on which the expression was
found, or -1 when it wasn’t found
...
log ("
// → 2
console
...
search (/\ S /) ) ;
"
...


The lastIndex property
The exec method similarly does not provide a convenient way to start
searching from a given position in the string
...

Regular expression objects have properties
...
Another
property is lastIndex, which controls, in some limited circumstances,
where the next match will start
...
Again, a more sane solution would have been to just allow
an extra argument to be passed to exec, but sanity is not a defining
characteristic of JavaScript’s regular expression interface
...
lastIndex = 3;

180

var match = pattern
...
log ( match
...
log ( pattern
...
If no match was found,
lastIndex is set back to zero, which is also the value it has in a newly
constructed regular expression object
...

Your regular expression might be accidentally starting at an index that
was left over from a previous call
...
log ( digit
...
log ( digit
...
When called with a global expression, instead of returning an array similar to that returned by exec, match
will find all matches of the pattern in the string and return an array
containing the matched strings
...
log (" Banana "
...
The cases where they
are necessary—calls to replace and places where you want to explicitly
use lastIndex—are typically the only places where you want to use them
...

var input = "A string with 3 numbers in it
...
";

181

var number = /\ b (\ d +) \ b /g ;
var match ;
while ( match = number
...
log (" Found " , match [1] , " at ", match
...
So by using match = number
...


Parsing an INI file
To conclude the chapter, we’ll look at a problem that calls for regular
expressions
...
(We will not actually
write that program here, just the part that reads the configuration file
...
) The configuration file looks like this:
searchengine = http :// www
...
com / search ?q= $1
spitefulness =9
...

; each section concerns an individual enemy
[ larry ]
fullname = Larry Doe
type = kindergarten bully
website = http :// www
...
com / CapeCanaveral /11451
[ gargamel ]
fullname = Gargamel
type = evil sorcerer
outputdir =/ home / marijn / enemies / gargamel

The exact rules for this format (which is actually a widely used format,
usually called an INI file) are as follows:
• Blank lines and lines starting with semicolons are ignored
...

• Lines containing an alphanumeric identifier followed by an = character add a setting to the current section
...

Our task is to convert a string like this into an array of objects, each
with a name property and an array of settings
...

Since the format has to be processed line by line, splitting up the file
into separate lines is a good start
...
split("\n") to do this
in Chapter 6
...
Given that the split method also allows a regular
expression as its argument, we can split on a regular expression like
/\r?\n/ to split in a way that allows both "\n" and "\r\n" between lines
...
split (/\ r ?\ n /)
...
test ( line )) {
return ;
} else if ( match = line
...
*) \] $ /) ) {
currentSection = { name : match [1] , fields : []};
categories
...
match (/^(\ w +) =(
...
fields
...
") ;
}
}) ;
return categories ;
}

183

This code goes over every line in the file, updating the “current section”
object as it goes along
...
Do you see how it works? The part
between the parentheses will match comments, and the ? will make sure
it also matches lines containing only whitespace
...
If so, it creates a new current section object, to
which subsequent settings will be added
...

If a line matches none of these forms, the function throws an error
...
Leaving these out results in code
that mostly works but behaves strangely for some input, which can be
a difficult bug to track down
...
match(
...
You often aren’t sure that your
call to match will succeed, so you can access the resulting object only
inside an if statement that tests for this
...


International characters
Because of JavaScript’s initial simplistic implementation and the fact
that this simplistic approach was later set in stone as standard behavior, JavaScript’s regular expressions are rather dumb about characters
that do not appear in the English language
...
Things like é or
ß, which most definitely are word characters, will not match \w (and will
match uppercase \W, the nonword category)
...

Some regular expression implementations in other programming languages have syntax to match specific Unicode character categories, such
as “all uppercase letters”, “all punctuation”, or “control characters”
...


Summary
Regular expressions are objects that represent patterns in strings
...

/abc/
A sequence of characters
/[abc]/
Any character from a set of characters
/[^abc]/ Any character not in a set of characters
/[0-9]/
Any character in a range of characters
/x+/
One or more occurrences of the pattern x
/x+?/
One or more occurrences, nongreedy
/x*/
Zero or more occurrences
/x?/
Zero or one occurrence
/x{2,4}/ Between two and four occurrences
/(abc)/
A group
/a|b|c/
Any one of several patterns
/\d/
Any digit character
/\w/
An alphanumeric character (“word character”)
/\s/
Any whitespace character
/
...
It also has an exec method that, when a match is found,
returns an array containing all matched groups
...

Strings have a match method to match them against a regular expression and a search method to search for one, returning only the starting
position of the match
...
Alternatively, you can pass a function to replace, which will be used to build up a replacement string based
on the match text and matched groups
...
The i option makes the match case insensitive, while the g
option makes the expression global, which, among other things, causes
the replace method to replace all instances instead of just the first
...

Regular expressions are a sharp tool with an awkward handle
...
Part of knowing how to use them
is resisting the urge to try to shoehorn things that they cannot sanely
express into them
...
Sometimes it helps to enter your expression into
an online tool like debuggex
...


Regexp golf
Code golf is a term used for the game of trying to express a particular
program in as few characters as possible
...

For each of the following items, write a regular expression to test
whether any of the given substrings occur in a string
...
Do not worry about word boundaries unless explicitly mentioned
...


186

1
...
pop and prop
3
...
Any word ending in ious
5
...
A word longer than six letters
7
...
Test each solution
with a few test strings
...
Now you want to replace all the dialogue
quotes with double quotes, while keeping the single quotes used in contractions like aren’t
...


Numbers again
A series of digits can be matched by the simple regular expression /\d+/
...
It
must support an optional minus or plus sign in front of the number,
the decimal dot, and exponent notation—5e-3 or 1E10— again with an
optional sign in front of the exponent
...
That is,
...
are valid JavaScript numbers, but a
lone dot isn’t
...
On a small scale, this shape is determined
by its division into functions and the blocks inside those functions
...

Shape follows more from the taste of the programmer than from the program’s intended functionality
...
Such a program can be made more
readable if we have a larger unit of organization
...
This chapter explores some of the benefits that such division provides and shows techniques for building modules in JavaScript
...
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
...

The benefits of organizing a program into several files or modules are
similar
...

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
...
It also makes the
program more difficult to change because prose tends to be more tightly

188

interconnected than code
...
The
“project” chapters of this book can be considered literate programs
...
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
...
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
...
JavaScript
does not
...

Namespace pollution, the problem of a lot of unrelated code having to
share a single set of global variable names, was mentioned in Chapter 4,
where the Math object was given as an example of an object that acts like
a module by grouping math-related functionality
...

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
...

In my program for spying on my enemies (see Chapter 9), I wrote a
function for reading configuration files
...
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

189

forget to also fix it in the other program
...

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
...

You can then automate the process of installing and upgrading external
modules (libraries)
...

This service exists
...
org)
...
It grew out of Node
...


Decoupling
Another important role of modules is isolating pieces of code from each
other, in the same way that the object interfaces from Chapter 6 do
...

As the module gets updated with bug fixes and new functionality, the
existing interface stays the same (it is stable) so that other modules can
use the new, improved version without any changes to themselves
...
It just means that existing functionality isn’t
removed and its meaning is not changed
...
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

190

range of situations
...
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
...
So
if we want our modules to have their own scope, we will have to base
them on functions
...
log ( dayName (1) ) ;
// → Monday

The dayName function is part of the module’s interface, but the names variable is not
...

We can do this:
var dayName = function () {
var names = [" Sunday " , " Monday " , " Tuesday ", " Wednesday ",
" Thursday " , " Friday " , " Saturday "];
return function ( number ) {
return names [ number ];
};
}() ;
console
...
This function is

191

created and immediately called, and its return value (the actual dayName
function) is stored in a variable
...

We can use a similar pattern to isolate code from the outside world
entirely
...
log ( square ( hundred ) ) ;
}) () ;
// → 10000

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
...

Why did we wrap the namespace function in a pair of parentheses?
This has to do with a quirk in JavaScript’s syntax
...
However,
if a statement starts with function, it is a function declaration, which
requires a name and, not being an expression, cannot be called by writing
parentheses after it
...


Objects as interfaces
Now imagine that we want to add another function to our day-of-theweek module, one that goes from a day name to a number
...

var weekDay = function () {
var names = [" Sunday " , " Monday " , " Tuesday ", " Wednesday ",
" Thursday " , " Friday " , " Saturday "];
return {

192

name : function ( number ) { return names [ number ]; },
number : function ( name ) { return names
...
log ( weekDay
...
number (" Sunday ") ));
// → Sunday

For bigger modules, gathering all the exported 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
...
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
...
)
( function ( exports ) {
var names = [" Sunday " , " Monday " , " Tuesday ", " Wednesday ",
" Thursday " , " Friday " , " Saturday "];
exports
...
number = function ( name ) {
return names
...
weekDay = {}) ;
console
...
name ( weekDay
...
The module will claim a single global variable and wrap
its code in a function in order to have its own private namespace
...

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
...

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
...
First, we want a function readFile,
which returns the content of a given file as a string
...
js, provide their own ways
of accessing files
...
)
Second, we need to be able to actually execute this string as JavaScript
code
...

The most obvious way is the special operator eval, which will execute
a string of code in the current scope
...

function evalAndReturnX ( code ) {
eval ( code ) ;
return x;
}
console
...
This takes two arguments: a string containing a comma-separated
list of argument names and a string containing the function’s body
...
log ( plusOne (4) ) ;
// → 5

This is precisely what we need for our modules
...


Require
The following is a minimal implementation of require:
function require ( name ) {
var code = new Function (" exports " , readFile ( name ));
var exports = {};
code ( exports ) ;
return exports ;
}
console
...
name (1) );
// → Monday

Since the new Function constructor wraps the module code in a function,
we don’t have to write a wrapping namespace function in the module file
itself
...
This removes a lot of clutter
from our example module
...
name = function ( number ) {
return names [ number ];
};
exports
...
indexOf ( name ) ;
};

195

When using this pattern, a module typically starts with a few variable
declarations that load the modules it depends on
...
log ( weekDay
...
dayNumber () ));

The simplistic implementation of require given previously has several
problems
...

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
...
For
example, a module might want to export only the constructor of the
object type it defines
...

The traditional solution for this is to provide modules with another
variable, module, which is an object that has a property exports
...

function require ( name ) {
if ( name in require
...
cache [ name ];
var code = new Function (" exports , module ", readFile ( name ));
var exports = {} , module = { exports : exports };
code ( exports , module ) ;
require
...
exports ;
return module
...
cache = Object
...

This style of module system is called CommonJS modules, after the
pseudo-standard that first specified it
...
js system
...

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
...
The reason for this
is that reading a file (module) from the Web is a lot slower than reading
it from the hard disk
...
This means that if every require call went
and fetched something from some faraway web server, the page would
freeze for a painfully long time while loading its scripts
...
This will look for
calls to require, resolve all dependencies, and gather the needed code into
a single big file
...

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
...

Our trivial program with dependencies would look like this in AMD:
define ([" weekDay " , " today "] , function ( weekDay , today ) {
console
...
name ( today
...
It takes first an array
of module names and then a function that takes one argument for each
dependency
...
Once all dependencies are loaded, define will
call the function it was given, with the interfaces of those dependencies
as arguments
...
The value used as their interface is whatever was returned by
the function passed to define
...
indexOf ( name ); }
};
}) ;

To be able to show a minimal implementation of define, we will pretend
we have a backgroundReadFile 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
...
)
For the purpose of keeping track of modules while they are being
loaded, the implementation of define will use objects that describe the
state of modules, telling us whether they are available yet and providing
their interface when they are
...
It uses a cache
object to avoid loading the same module twice
...
create ( null );
var currentMod = null ;
function getModule ( name ) {
if ( name in defineCache )
return defineCache [ name ];
var module = { exports : null ,

198

loaded : false ,
onLoad : []};
defineCache [ name ] = module ;
backgroundReadFile ( name , function ( code ) {
currentMod = module ;
new Function ("" , code ) () ;
}) ;
return module ;
}

We assume the loaded file also contains a (single) call to define
...
We will come back to this mechanism in a moment
...
Its task is to schedule
the moduleFunction (the function that contains the module’s actual code)
to be run whenever those dependencies are 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
...

function define ( depNames , moduleFunction ) {
var myMod = currentMod ;
var deps = depNames
...
forEach ( function ( mod ) {
if (! mod
...
onLoad
...
every ( function ( m) { return m
...
map ( function ( m ) { return m
...
apply ( null , args );
if ( myMod ) {

199

myMod
...
loaded = true ;
myMod
...
forEach ( function (f) { f () ; }) ;
}
}
whenDepsLoaded () ;
}

When all dependencies are available, whenDepsLoaded calls the function that
holds the module, giving it the dependencies’ interfaces as arguments
...
Remember that getModule, just before
evaluating the code for a module, stored the corresponding module object
in currentMod
...

This code is a lot harder to follow than the require function
...
Instead, multiple
operations are set up to happen at some unspecified time in the future,
which obscures the way the code executes
...
The RequireJS (requirejs
...


Interface design
Designing interfaces for modules and object types is one of the subtler
aspects of programming
...
Finding a way that works well requires insight
and foresight
...
Experience will teach you what
works and what doesn’t
...
Fix it, or wrap it in a new interface that works better for
you
...
Thus,
try to follow conventions
...
That way, it’ll feel familiar to people
who know the existing interface
...
It can be tempting to make an unnecessarily clever interface
with the justification that it’s more convenient to use
...
Or you could provide dozens of
specialized convenience functions that provide slightly different flavors
of your module’s functionality
...


Composability
In your interfaces, try to use the simplest data structures possible and
make functions do a single, clear thing
...

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
...
This is an example of poor composability—the module
cannot be easily composed with other code
...
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
...
On the other hand,
if we define the spell-checking interface so that you can pass it a simple

201

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
...
On the one hand,
you do not want to overload the user of your interface with details
...
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
...
The
second can usually be built easily using the tools provided by the first
...
The low-level interface would allow full control over
email headers, attachments, HTML mail, and so on
...
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
...
Function scopes can be
used as internal namespaces for the module, and objects can be used to
store sets of exported values
...
One
is called CommonJS Modules and revolves around a require function that
fetches a module by name and returns its interface
...


Exercises
Month names
Write a simple module similar to the weekDay module that can convert
month numbers (zero-based, as in the Date type) to names and can convert names back to numbers
...


A return to electronic life
Hoping that Chapter 7 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
...
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
...
Aim for three to five modules
...

There is no single correct solution here
...


Circular dependencies
A tricky subject in dependency management is circular dependencies,
where module A depends on B, and B also depends on A
...
CommonJS modules allow a limited form: it
works as long as the modules do not replace their default exports object
with another value and start accessing each other’s interface only after
they finish loading
...


204

“The evaluator, which determines the meaning of expressions
in a programming language, is just another program
...

The main thing I want to show in this chapter is that there is no magic
involved in building your own language
...
But with a little reading and tinkering, such
things often turn out to be quite mundane
...
It will be a tiny,
simple language but one that is powerful enough to express any computation you can think of
...


Parsing
The most immediately visible part of a programming language is its
syntax, or notation
...
If the text does not form a valid program, the
parser should complain and point out the error
...
Everything in
Egg is an expression
...
Applications are used for function calls but
also for constructs such as if or while
...
A string is simply a sequence of characters that are
not double quotes, wrapped in double quotes
...
Variable names can consist of any character that is not whitespace

205

and does not have a special meaning in the syntax
...

do ( define (x , 10) ,
if ( >(x , 5) ,
print (" large ") ,
print (" small ") ) )

The uniformity of the Egg language means that things that are operators
in JavaScript (such as >) are normal variables in this language, applied
just like other functions
...

The data structure that the parser will use to describe a program will
consist of expression objects, each of which has a type property indicating
the kind of expression it is and other properties to describe its content
...
Their
value property contains the string or number value that they represent
...
Such objects
have a name property that holds the identifier’s name as a string
...
They have an operator property
that refers to the expression that is being applied, and they have an args
property that refers to an array of argument expressions
...
If you imagine the objects
as dots and the links between them as lines between those dots, it has
a treelike shape
...


do
define
x
10
if
>
x
5
print
"large"
print
"small"
Contrast this to the parser we wrote for the configuration file format in
Chapter 9, which had a simple structure: it split the input into lines and
handled those lines one at a time
...

Here we must find a different approach
...
Application expressions
contain other expressions
...

We define a function parseExpression, which takes a string as input and
returns an object containing the data structure for the expression at the
start of the string, along with the part of the string left after parsing
this expression
...
This text may
in turn contain more arguments or may be the closing parenthesis that
ends the list of arguments
...
exec ( program ))
expr = { type : " value ", value : match [1]};
else if ( match = /^\ d +\ b /
...
exec ( program ))
expr = { type : " word ", name : match [0]};
else
throw new SyntaxError (" Unexpected syntax : " + program );
return parseApply ( expr , program
...
length ));
}
function skipSpace ( string ) {
var first = string
...
slice ( first );
}

Because Egg allows any amount of whitespace between its elements, we
have to repeatedly cut the whitespace off the start of the program string
...

After skipping any leading space, parseExpression uses three regular expressions to spot the three simple (atomic) elements that Egg supports:
strings, numbers, and words
...
If the input does not
match one of these three forms, it is not a valid expression, and the
parser throws an error
...

We can then cut off the part that we matched from the program string
and pass that, along with the object for the expression, to parseApply,
which checks whether the expression is an application
...

function parseApply ( expr , program ) {
program = skipSpace ( program );
if ( program [0] != "(")

208

return { expr : expr , rest : program };
program = skipSpace ( program
...
args
...
expr );
program = skipSpace ( arg
...
slice (1) );
else if ( program [0] != ") ")
throw new SyntaxError (" Expected  ,  or  )  ") ;
}
return parseApply ( expr , program
...

Otherwise, it skips the opening parenthesis and creates the syntax
tree object for this application expression
...
The recursion is indirect, through parseApply and parseExpression
calling each other
...

This is all we need to parse Egg
...

function parse ( program ) {
var result = parseExpression ( program );
if ( skipSpace ( result
...
length > 0)
throw new SyntaxError (" Unexpected text after program ") ;
return result
...
log ( parse ("+( a , 10) ") ) ;

209

//
//
//
//



{ type : " apply " ,
operator : { type : " word " , name : "+"} ,
args : [{ type : " word " , name : " a "} ,
{ type : " value " , value : 10}]}

It works! It doesn’t give us very helpful information when it fails and
doesn’t store the line and column on which each expression starts, which
might be helpful when reporting errors later, but it’s good enough for
our purposes
...
You give it a syntax tree and
an environment object that associates names with values, and it will
evaluate the expression that the tree represents and return the value
that this produces
...
type ) {
case " value ":
return expr
...
name in env )
return env [ expr
...
name );
case " apply ":
if ( expr
...
type == " word " &&
expr
...
name in specialForms )
return specialForms [ expr
...
name ]( expr
...
operator , env );
if ( typeof op != " function ")
throw new TypeError (" Applying a non - function
...
apply ( null , expr
...
map ( function ( arg ) {
return evaluate ( arg , env ) ;
}) ) ;

210

}
}
var specialForms = Object
...
A literal value
expression simply produces its value
...
) For a variable, we must check whether
it is actually defined in the environment and, if it is, fetch the variable’s
value
...
If they are a special form, like if,
we do not evaluate anything and simply pass the argument expressions,
along with the environment, to the function that handles this form
...

We will use plain JavaScript function values to represent Egg’s function
values
...

The recursive structure of evaluate resembles the similar structure of
the parser
...
It would
also be possible to integrate the parser with the evaluator and evaluate
during parsing, but splitting them up this way makes the program more
readable
...
It is that simple
...


Special forms
The specialForms object is used to define special syntax in Egg
...
It is
currently empty
...

specialForms [" if "] = function ( args , env ) {
if ( args
...
It will evaluate the
first, and if the result isn’t the value false, it will evaluate the second
...
This if form is more similar to
JavaScript’s ternary ?: operator than to JavaScript’s if
...

Egg differs from JavaScript in how it handles the condition value to if
...

The reason we need to represent if as a special form, rather than a
regular function, is that all arguments to functions are evaluated before
the function is called, whereas if should evaluate only either its second
or its third argument, depending on the value of the first
...

specialForms [" while "] = function ( args , env ) {
if ( args
...

return false ;
};

Another basic building block is do, which executes all its arguments from
top to bottom
...

specialForms [" do "] = function ( args , env ) {
var value = false ;
args
...
It expects a word as its first argument and an expression producing the value to assign to that word as its second argument
...

We’ll make it return the value that was assigned (just like JavaScript’s
= operator)
...
length != 2 || args [0]
...
name ] = value ;
return value ;
};

The environment
The environment accepted by evaluate is an object with properties whose
names correspond to variable names and whose values correspond to the
values those variables are bound to
...

To be able to use the if construct we just defined, we must have access
to Boolean values
...
We simply bind two variables to the values
true and false and use those
...
create ( null );
topEnv [" true "] = true ;
topEnv [" false "] = false ;

We can now evaluate a simple expression that negates a Boolean value
...
log ( evaluate ( prog , topEnv ));
// → false

To supply basic arithmetic and comparison operators, we will also add

213

some function values to the environment
...

["+" , " -" , "*" , "/" , "==" , " <" , " >"]
...
log in a
function and call it print
...
log ( value ) ;
return value ;
};

That gives us enough elementary tools to write simple programs
...

It creates a fresh environment and parses and evaluates the strings we
give it as a single program
...
create ( topEnv ) ;
var program = Array
...
slice

...
join ("\ n ") ;
return evaluate ( parse ( program ) , env );
}

The use of Array
...
slice
...
It takes
all the arguments given to run and treats them as the lines of a program
...
It is clearly uglier than the

214

equivalent JavaScript program but not bad for a language implemented
in less than 150 lines of code
...

Fortunately, it is not hard to add a fun construct, which treats its last
argument as the function’s body and treats all the arguments before that
as the names of the function’s arguments
...
length )
throw new SyntaxError (" Functions need a body ") ;
function name ( expr ) {
if ( expr
...
name ;
}
var argNames = args
...
length - 1)
...
length - 1];
return function () {
if ( arguments
...
length )
throw new TypeError (" Wrong number of arguments ") ;
var localEnv = Object
...
length ; i ++)
localEnv [ argNames [i ]] = arguments [i ];
return evaluate ( body , localEnv );
};
};

Functions in Egg have their own local environment, just like in JavaScript
...
create to make a new object that has access to the variables in the outer environment (its prototype) but that can also contain
new variables without modifying that outer scope
...
It then evaluates the function
body in this environment and returns the result
...
During evaluation, it acts directly
on the representation of the program produced by the parser
...
For example, in well-designed languages it is
obvious, for each use of a variable, which variable is being referred to,
without actually running the program
...

Traditionally, compilation involves converting the program to machine
code, the raw format that a computer’s processor can execute
...

It would be possible to write an alternative evaluation strategy for
Egg, one that first converts the program to a JavaScript program, uses
new Function to invoke the JavaScript compiler on it, and then runs the
result
...

If you are interested in this topic and willing to spend some time on
it, I encourage you to try to implement such a compiler as an exercise
...
Similarly,
the values in Egg are just regular old JavaScript values
...
Regardless, this example hopefully gave you an
impression of the way programming languages work
...
Though the toy language in this
chapter doesn’t do anything that couldn’t be done better in JavaScript,
there are situations where writing small languages helps get real work
done
...
If JavaScript didn’t come equipped with regular expressions,
you could write your own parser and evaluator for such a sublanguage
...
JavaScript might not be the most effective way to
do this
...
Such a language
can be more expressive than a general-purpose language because it is

217

designed to express exactly the things that need expressing in its domain
and nothing else
...
) to construct an array containing the argument
values, length(array) to get an array’s length, and element(array, n) to
fetch the nth element from an array
...

The following program illustrates this: function f returns a function
that adds its argument to f’s argument, meaning that it needs access to
the local scope inside f to be able to use variable a
...


Comments
It would be nice if we could write comments in Egg
...

We do not have to make any big changes to the parser to support
this
...
Make this change
...
This
construct acts as a way both to define new variables and to give existing
ones a new value
...
When you try to give a nonlocal
variable a new value, you will end up defining a local one with the same
name instead
...
)
Add a special form set, similar to define, which gives a variable a new
value, updating the variable in an outer scope if it doesn’t already exist in
the inner scope
...

The technique of representing scopes as simple objects, which has made
things convenient so far, will get in your way a little at this point
...
getPrototypeOf function, which returns the
prototype of an object
...
prototype, so if you want to call hasOwnProperty on them, you have
to use this clumsy expression:
Object
...
hasOwnProperty
...


219

“The browser is a really hostile programming environment
...
Without web
browsers, there would be no JavaScript
...

Web technology has, from the start, been decentralized, not just technically but also in the way it has evolved
...

This is both a blessing and a curse
...
On the other hand, the haphazard way in which the Web
was developed means that the resulting system is not exactly a shining
example of internal consistency
...


Networks and the Internet
Computer networks have been around since the 1950s
...

If connecting two machines in the same building allows us to do wonderful things, connecting machines all over the planet should be even
better
...
It has
lived up to its promise
...

For any effective communication to arise out of this bit-spewing, the
computers at both ends must know what the bits are supposed to repre-

220

sent
...

A network protocol describes a style of communication over a network
...

For example, a simple chat protocol might consist of one computer
sending the bits that represent the text “CHAT?” to another machine
and the other responding with “OK!” to confirm that it understands the
protocol
...

Most protocols are built on top of other protocols
...

Ensuring those things is already a rather difficult technical problem
...
All Internet-connected devices “speak” it, and most communication on the Internet is built on top of it
...
To be able to
listen for different kinds of communication at the same time on a single
machine, each listener has a number (called a port) associated with it
...
For example, when we want to send an email using the SMTP protocol, the
machine through which we send it is expected to be listening on port 25
...
If the target machine can
be reached and is listening on that port, the connection is successfully
created
...

Such a connection acts as a two-way pipe through which bits can flow—
the machines on both ends can put data into it
...
This is a convenient model
...


221

The Web
The World Wide Web (not to be confused with the Internet as a whole)
is a set of protocols and formats that allow us to visit web pages in a
browser
...

To add content to the Web, all you need to do is connect a machine to
the Internet, and have it listen on port 80, using the Hypertext Transfer Protocol (HTTP)
...

Each document on the Web is named by a Uniform Resource Locator
(URL), which looks something like this:
http :// eloquentjavascript
...
html
|
|
|
|
protocol
server
path

The first part tells us that this URL uses the HTTP protocol (as opposed
to, for example, encrypted HTTP, which would be https:// )
...
Last is a path string that identifies the specific document (or
resource) we are interested in
...
187
...
82
...
But lists of more or less random numbers are
hard to remember and awkward to type, so you can instead register a
domain name to point toward a specific machine or set of machines
...
net to point at the IP address of a machine
I control and can thus use that domain name to serve web pages
...
First, your browser
has to find out what address eloquentjavascript
...
Then, using
the HTTP protocol, it makes a connection to the server at that address
and asks for the resource /12_browser
...

We will take a closer look at the HTTP protocol in Chapter 17
...
An HTML document contains text, as well
as tags that give structure to the text, describing things such as links,
paragraphs, and headings
...


I also wrote a book ! Read it
...
In this case, the destination of the link is indicated
with href="http://eloquentjavascript
...

Some kinds of tags do not enclose anything and thus do not need to
be closed
...
com/image

...

To be able to include angle brackets in the text of a document, even
though they have a special meaning in HTML, yet another form of special
notation has to be introduced
...
In HTML, an ampersand (&) character followed by a word and
a semicolon (;) is called an entity, and will be replaced by the character
it encodes
...

Since this mechanism gives ampersand characters a special meaning, too,
those need to be escaped as &
...

HTML is parsed in a remarkably error-tolerant way
...
The way in
which this is done has been standardized, and you can rely on all modern
browsers to do it in the same way
...

I also wrote a book ! Read it
...


224

The , , and tags are gone completely
...
Furthermore, I am no longer explicitly closing the paragraphs since opening a
new paragraph or ending the document will close them implicitly
...

This book will usually omit the , , and tags from
examples to keep them short and free of clutter
...

I will also usually omit the doctype
...
Browsers will often do
ridiculous things when you forget them
...


HTML and JavaScript
In the context of this book, the most important HTML tag is , even if it refers to
a script file and doesn’t contain any code
...

Some attributes can also contain a JavaScript program
...

< button onclick =" alert (  Boom !  ) ;" > DO NOT PRESS

Note that I had to use single quotes for the string in the onclick attribute
because double quotes are already used to quote the whole attribute
...


In the sandbox
Running programs downloaded from the Internet is potentially dangerous
...
Running programs by people who do not mean well is how you get your computer infected by
viruses, your data stolen, and your accounts hacked
...
This is why browsers severely limit
the things a JavaScript program may do: it can’t look at the files on
your computer or modify anything not related to the web page it was
embedded in
...
But
you should imagine this particular kind of sandbox as having a cage of
thick steel bars over it, which makes it somewhat different from your
typical playground sandbox
...
Lots of useful functionality, such as communicating with
other servers or reading the content of the copy-paste clipboard, can
also be used to do problematic, privacy-invading things
...
The browser developers respond by fixing the hole,

226

and all is well again—that is, until the next problem is discovered, and
hopefully publicized, rather than secretly exploited by some government
or mafia
...
After a few years, the balance had shifted to Netscape, which
was then, in turn, largely supplanted by Microsoft’s Internet Explorer
...
Since
most users used the same browser, websites would simply start using
those features—never mind the other browsers
...

Web developers were left with not one unified Web but two or three incompatible platforms
...
Life was hard for people writing web pages
...
Because Microsoft was
not particularly interested in staying competitive at the time, Firefox
took quite a chunk of market share away from it
...

The new players had a more serious attitude toward standards and
better engineering practices, leading to less incompatibility and fewer
bugs
...
If you are starting to learn web development
today, consider yourself lucky
...

That is not to say that the situation is perfect just yet
...
Until those browsers die out entirely, writing
websites that work for them will require a lot of arcane knowledge about
their shortcomings and quirks
...


227

Rather, it aims to present the modern, sane style of web programming
...
The browser builds up a model of the
document’s structure and then uses this model to draw the page on the
screen
...
You can read from the model and
also change it
...


Document structure
You can imagine an HTML document as a nested set of boxes
...
Here’s the example document from the previous chapter:

< html >

< title > My home page


My home page

Hello , I am Marijn and this is my home page
...
net "> here

...

p

a

I also wrote a book! Read it
here


...
For each box, there is an object, which we can interact with
to find out things such as what HTML tag it represents and which boxes
and text it contains
...

The global variable document gives us access to these objects
...
It also provides
the properties head and body, which hold the objects for those elements
...
Their
structures are strikingly similar to the structure of a browser’s document
...
This shape is typical of nested structures where
elements can contain sub-elements that are similar to themselves
...
In the case of the DOM, document
...

Trees come up a lot in computer science
...

A typical tree has different kinds of nodes
...
Application
nodes always have children, whereas variables and values are leaves, or
nodes without children
...
Nodes for regular elements, which represent HTML tags, determine the structure of the document
...
An example of such a node is document
...
Some
of these children can be leaf nodes, such as pieces of text or comments
(comments are written between in HTML)
...
Regular elements have
the value 1, which is also defined as the constant property document
...
Text nodes, representing a section of text in the document, have the value 3 (document
...
Comments have the value 8
(document
...

So another way to visualize our document tree is as follows:

html

head

title

My home page

body

h1

My home page

p

Hello! I am
...

a

...


The standard
Using cryptic numeric codes to represent node types is not a very JavaScriptlike thing to do
...
The reason for this is
that the DOM wasn’t designed for just JavaScript
...

This is unfortunate
...
But in this case, the
advantage (cross-language consistency) isn’t all that compelling
...

As an example of such poor integration, consider the childNodes property that element nodes in the DOM have
...
But it is an instance of the NodeList type, not a
real array, so it does not have methods such as slice and forEach
...
For example, there is
no way to create a new node and immediately add children or attributes
to it
...
Code
that interacts heavily with the DOM tends to get long, repetitive, and
ugly
...
Since JavaScript allows us to create our
own abstractions, it is easy to write some helper functions that allow you
to express the operations you are performing in a clearer and shorter
way
...


232

Moving through the tree
DOM nodes contain a wealth of links to other nearby nodes
...


parentNode

nextSibling
2

p

I also wrote a book!
...
Likewise, every
element node (node type 1) has a childNodes property that points to an
array-like object holding its children
...
But JavaScript also gives you access to a number of additional convenience links
...
Similarly, previousSibling and nextSibling point to adjacent
nodes, which are nodes with the same parent that appear immediately
before or after the node itself
...

When dealing with a nested data structure like this one, recursive
functions are often useful
...
nodeType == document
...
childNodes
...
childNodes [i], string ))
return true ;
}
return false ;
} else if ( node
...
TEXT_NODE ) {
return node
...
indexOf ( string ) > -1;
}
}
console
...
body , " book ") );
// → true

The nodeValue property of a text node refers to the string of text that it
represents
...

But if we want to find a specific node in the document, reaching it by
starting at document
...
Doing so bakes assumptions into our program about the
precise structure of the document—a structure we might want to change
later
...
The example document’s body tag does
not have just three children (

and two

elements) but actually has
seven: those three, plus the spaces before, after, and between them
...
It’d be better if we could say “Get the first link
in the document”
...

var link = document
...
getElementsByTagName (" a ") [0];
console
...
href ) ;

All element nodes have a getElementsByTagName method, which collects all
elements with the given tag name that are descendants (direct or indirect
children) of the given node and returns them as an array-like object
...
getElementById

instead
...
png " >


< script >
var ostrich = document
...
log ( ostrich
...


Changing the document
Almost everything about the DOM data structure can be changed
...
The removeChild method removes the given child node from the
document
...

One

Two

Three


< script >
var paragraphs = document
...
getElementsByTagName (" p ") ;
document
...
insertBefore ( paragraphs [2] , paragraphs [0]) ;


A node can exist in the document in only one place
...
All operations that insert a node somewhere will, as
a side effect, cause it to be removed from its current position (if it has
one)
...
It takes as arguments two nodes: a new node and the node to be

235

replaced
...
Note that both replaceChild and insertBefore expect the new
node as their first argument
...

This involves not only removing the images but adding a new text node
to replace them
...
createTextNode method
...
png " alt =" Cat "> in the
< img src =" img / hat
...


< button onclick =" replaceImages () "> Replace


< script >
function replaceImages () {
var images = document
...
getElementsByTagName (" img ") ;
for ( var i = images
...
alt ) {
var text = document
...
alt );
image
...
replaceChild ( text , image );
}
}
}


Given a string, createTextNode gives us a type 3 DOM node (a text node),
which we can insert into the document to make it show up on the screen
...
This is necessary because the node list returned by a method
like getElementsByTagName (or a property like childNodes) is live
...
If we started from the front,
removing the first image would cause the list to lose its first element so
that the second time the loop repeats, where i is 1, it would stop because

236

the length of the collection is now also 1
...

var arrayish = {0: " one ", 1: " two " , length : 2};
var real = Array
...
slice
...
forEach ( function ( elt ) { console
...

createElement method
...

The following example defines a utility elt, which creates an element
node and treats the rest of its arguments as children to that node
...

< blockquote id =" quote " >
No book can ever be finished
...


< script >
function elt ( type ) {
var node = document
...
length ; i ++) {
var child = arguments [ i ];
if ( typeof child == " string ")
child = document
...
appendChild ( child );
}
return node ;
}
document
...
appendChild (
elt (" footer " , ---"" ,
elt (" strong " , " Karl Popper ") ,
" , preface to the second editon of ",
elt (" em " , " The Open Society and Its Enemies ") ,
" , 1950") ) ;

237



This is what the resulting document looks like:

Attributes
Some element attributes, such as href for links, can be accessed through
a property of the same name on the element’s DOM object
...

But HTML allows you to set any attribute you want on nodes
...

If you make up your own attribute names, though, such attributes will
not be present as a property on the element’s node
...

The launch code is 00000000
...


< script >
var paras = document
...
getElementsByTagName (" p ") ;
Array
...
forEach
...
getAttribute (" data - classified ") == " secret ")
para
...
removeChild ( para );
}) ;


I recommended prefixing the names of such made-up attributes with
data- to ensure they do not conflict with any other attributes
...


238

function highlightCode ( node , keywords ) {
var text = node
...
textContent = ""; // Clear the node
var match , pos = 0;
while ( match = keywords
...
slice ( pos , match
...
appendChild ( document
...
createElement (" strong ") ;
strong
...
createTextNode ( match [0]) );
node
...
lastIndex ;
}
var after = text
...
appendChild ( document
...

The textContent property is used to get all the text in the node and is
then set to an empty string, which has the effect of emptying the node
...

We can automatically highlight all programs on the page by looping
over all the
 elements that have a data-language attribute and calling highlightCode on each one with the correct regular expression for the
language
...
etc */
};
function highlightAllCode () {
var pres = document
...
getElementsByTagName (" pre ") ;
for ( var i = 0; i < pres
...
getAttribute (" data - language ") ;
if ( languages
...
For historical reasons—some old JavaScript
implementations could not handle property names that matched keywords or reserved words—the property used to access this attribute is
called className
...


Layout
You might have noticed that different types of elements are laid out
differently
...

These are called block elements
...
Such elements are called inline elements
...

This layout is then used to actually draw the document
...

The offsetWidth and offsetHeight properties give you the space the element
takes up in pixels
...
Similarly, clientWidth and clientHeight give you the size of
the space inside the element, ignoring border width
...
body
...
log (" clientHeight :" , para
...
log (" offsetHeight :" , para
...


The most effective way to find the precise position of an element on the
screen is the getBoundingClientRect method
...
If you want
them relative to the whole document, you must add the current scroll
position, found under the global pageXOffset and pageYOffset variables
...
In the interest of
speed, browser engines do not immediately re-layout a document every
time it is changed but rather wait as long as they can
...
When a program asks for the position or size of something
by reading properties such as offsetHeight or calling getBoundingClientRect,
providing correct information also requires computing a layout
...
The following code shows an
example of this
...

< span id =" one " >


< span id =" two " >



241

< script >
function time ( name , action ) {
var start = Date
...
log ( name , " took " , Date
...
getElementById (" one ") ;
while ( target
...
appendChild ( document
...
getElementById (" two ") ;
target
...
createTextNode (" XXXXX ") );
var total = Math
...
offsetWidth / 5) );
for ( var i = 5; i < total ; i ++)
target
...
createTextNode (" X ") );
}) ;
// → clever took 1 ms


Styling
We have seen that different HTML elements display different behavior
...
Some add styling, such as
making its content bold and making it blue and underlining
it
...
But
the default styling associated with an element, such as the text color or
underline, can be changed by us
...
" > Normal link


< a href ="
...


A style attribute may contain one or more declarations, which are a
property (such as color) followed by a colon and a value (such as green)
...

There are a lot of aspects that can be influenced by styling
...

This text is displayed < strong > inline ,
< strong style =" display : block " > as a block , and
< strong style =" display : none "> not at all
...
The last tag is not displayed
at all—display: none prevents an element from showing up on the screen
...
It is often preferable to removing them
from the document entirely because it makes it easy to reveal them again
at a later time
...
This property holds an object that has properties for all possible style properties
...


Pretty text


< script >

243

var para = document
...
log ( para
...
color );
para
...
color = " magenta ";


Some style property names contain dashes, such as font-family
...
fontFamily)
...

A style sheet is a set of rules for how to style elements in a document
...

< style >
strong {
font - style : italic ;
color : gray ;
}

Now < strong > strong text is italic and gray
...
In the previous
example, the default styling for tags, which gives them fontweight: bold, is overlaid by the rule in the