📄 Page
1
(This page has no text content)
📄 Page
2
Eloquent JavaScript 4th edition Marijn Haverbeke
📄 Page
3
Copyright © 2024 by Marijn Haverbeke This work is licensed under a Creative Commons attribution-noncommercial license (http://creativecommons.org/licenses/by-nc/3.0/). All code in the book may also be considered licensed under an MIT license (https://eloquentjavascript. net/code/LICENSE). The illustrations are contributed by various artists: Cover by Péchane Sumi- e. Chapter illustrations by Madalina Tantareanu. Pixel art in Chapters 7 and 16 by Antonio Perdomo Pastor. Regular expression diagrams in Chapter 9 generated with regexper.com by Jeff Avallone. Village photograph in Chapter 11 by Fabrice Creuzot. Game concept for Chapter 16 by Thomas Palef. You can buy a print version of this book, with an extra bonus chapter included, printed by No Starch Press at http://a-fwd.com/com=marijhaver-20&asin- com=1593279507. i
📄 Page
4
Contents Introduction 1 On programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Why language matters . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 What is JavaScript? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Code, and what to do with it . . . . . . . . . . . . . . . . . . . . . . . 7 Overview of this book . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Typographic conventions . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1 Values, Types, and Operators 10 Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Unary operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Boolean values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Empty values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Automatic type conversion . . . . . . . . . . . . . . . . . . . . . . . . . 18 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2 Program Structure 21 Expressions and statements . . . . . . . . . . . . . . . . . . . . . . . . 21 Bindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Binding names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 The environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 The console.log function . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Return values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Control flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Conditional execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 while and do loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Indenting Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 for loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Breaking Out of a Loop . . . . . . . . . . . . . . . . . . . . . . . . . . 32 ii
📄 Page
5
Updating bindings succinctly . . . . . . . . . . . . . . . . . . . . . . . 32 Dispatching on a value with switch . . . . . . . . . . . . . . . . . . . . 33 Capitalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3 Functions 38 Defining a function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Bindings and scopes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Nested scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Functions as values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Declaration notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Arrow functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 The call stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Optional Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Closure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Growing functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Functions and side effects . . . . . . . . . . . . . . . . . . . . . . . . . 52 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4 Data Structures: Objects and Arrays 55 The weresquirrel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Data sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Mutability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 The lycanthrope’s log . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Computing correlation . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Array loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 The final analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Further arrayology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Strings and their properties . . . . . . . . . . . . . . . . . . . . . . . . 69 Rest parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 The Math object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Destructuring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Optional property access . . . . . . . . . . . . . . . . . . . . . . . . . . 74 iii
📄 Page
6
JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5 Higher-Order Functions 79 Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Abstracting repetition . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Higher-order functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Script data set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Filtering arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Transforming with map . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Summarizing with reduce . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Composability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Strings and character codes . . . . . . . . . . . . . . . . . . . . . . . . 88 Recognizing text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 6 The Secret Life of Objects 93 Abstract Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Private Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Overriding derived properties . . . . . . . . . . . . . . . . . . . . . . . 99 Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Getters, setters, and statics . . . . . . . . . . . . . . . . . . . . . . . . 103 Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 The iterator interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 The instanceof operator . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 7 Project: A Robot 112 Meadowfield . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 The task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Persistent data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 iv
📄 Page
7
The mail truck’s route . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Pathfinding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 8 Bugs and Errors 123 Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Strict mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Error propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Cleaning up after exceptions . . . . . . . . . . . . . . . . . . . . . . . . 131 Selective catching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 9 Regular Expressions 138 Creating a regular expression . . . . . . . . . . . . . . . . . . . . . . . 138 Testing for matches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Sets of characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 International characters . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Repeating parts of a pattern . . . . . . . . . . . . . . . . . . . . . . . . 142 Grouping subexpressions . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Matches and groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 The Date class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Boundaries and look-ahead . . . . . . . . . . . . . . . . . . . . . . . . . 145 Choice patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 The mechanics of matching . . . . . . . . . . . . . . . . . . . . . . . . 147 Backtracking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 The replace method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 Greed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Dynamically creating RegExp objects . . . . . . . . . . . . . . . . . . 152 The search method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 The lastIndex property . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Parsing an INI file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Code units and characters . . . . . . . . . . . . . . . . . . . . . . . . . 157 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 v
📄 Page
8
10 Modules 161 Modular programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 ES modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 CommonJS modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Building and bundling . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Module design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 11 Asynchronous Programming 173 Asynchronicity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 Promises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 Failure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Carla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Breaking In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 Async functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Generators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 A Corvid Art Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 The event loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Asynchronous bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 12 Project: A Programming Language 193 Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 The evaluator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Special forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 The environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Cheating . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 13 JavaScript and the Browser 206 Networks and the Internet . . . . . . . . . . . . . . . . . . . . . . . . . 206 The Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 HTML and JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 vi
📄 Page
9
In the sandbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Compatibility and the browser wars . . . . . . . . . . . . . . . . . . . 212 14 The Document Object Model 214 Document structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 The standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 Moving through the tree . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Finding elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Changing the document . . . . . . . . . . . . . . . . . . . . . . . . . . 219 Creating nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Styling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Cascading styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Query selectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Positioning and animating . . . . . . . . . . . . . . . . . . . . . . . . . 228 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 15 Handling Events 233 Event handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Events and DOM nodes . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Event objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 Default actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Key events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Pointer events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Scroll events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Focus events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Load event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Events and the event loop . . . . . . . . . . . . . . . . . . . . . . . . . 245 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 Debouncing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 16 Project: A Platform Game 251 The game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 The technology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 vii
📄 Page
10
Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 Reading a level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Actors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Drawing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Motion and collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Actor updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Tracking keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 Running the game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 17 Drawing on Canvas 273 SVG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 The canvas element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 Lines and surfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Drawing a pie chart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Transformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Storing and clearing transformations . . . . . . . . . . . . . . . . . . . 286 Back to the game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 Choosing a graphics interface . . . . . . . . . . . . . . . . . . . . . . . 292 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 18 HTTP and Forms 296 The protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Browsers and HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Fetch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 HTTP sandboxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 Appreciating HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 Security and HTTPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Form fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Focus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Disabled fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 The form as a whole . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Text fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Checkboxes and radio buttons . . . . . . . . . . . . . . . . . . . . . . . 308 Select fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 viii
📄 Page
11
File fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 Storing data client-side . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 19 Project: A Pixel Art Editor 317 Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 The state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 DOM building . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 The canvas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321 The application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 Drawing tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 Saving and loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Undo history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Let’s draw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Why is this so hard? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 20 Node.js 337 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 The node command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Installing with NPM . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 The file system module . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 The HTTP module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 A file server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 21 Project: Skill-Sharing Website 354 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 Long polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 HTTP interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 The server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 The client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 Exercise Hints 373 Program Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 ix
📄 Page
12
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 Data Structures: Objects and Arrays . . . . . . . . . . . . . . . . . . . 375 Higher-Order Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 The Secret Life of Objects . . . . . . . . . . . . . . . . . . . . . . . . . 378 Project: A Robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Bugs and Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 Asynchronous Programming . . . . . . . . . . . . . . . . . . . . . . . . 382 Project: A Programming Language . . . . . . . . . . . . . . . . . . . . 384 The Document Object Model . . . . . . . . . . . . . . . . . . . . . . . 385 Handling Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 Project: A Platform Game . . . . . . . . . . . . . . . . . . . . . . . . . 387 Drawing on Canvas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 HTTP and Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 Project: A Pixel Art Editor . . . . . . . . . . . . . . . . . . . . . . . . 391 Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Project: Skill-Sharing Website . . . . . . . . . . . . . . . . . . . . . . . 394 x
📄 Page
13
“We think we are creating the system for our own purposes. We believe we are making it in our own image... But the computer is not really like us. It is a projection of a very slim part of ourselves: that portion devoted to logic, order, rule, and clarity.” —Ellen Ullman, Close to the Machine: Technophilia and its Discontents Introduction This is a book about instructing computers. Computers are about as common as screwdrivers today, but they are quite a bit more complex, and making them do what you want them to do isn’t always easy. If the task you have for your computer is a common, well-understood one, such as showing you your email or acting like a calculator, you can open the appropriate application and get to work. But for unique or open-ended tasks, there often is no appropriate application. That is where programming may come in. Programming is the act of con- structing a program—a set of precise instructions telling a computer what to do. Because computers are dumb, pedantic beasts, programming is fundamentally tedious and frustrating. Fortunately, if you can get over that fact—and maybe even enjoy the rigor of thinking in terms that dumb machines can deal with—programming can be rewarding. It allows you to do things in seconds that would take forever by hand. It is a way to make your computer tool do things that it couldn’t do before. On top of that, it makes for a wonderful game of puzzle solving and abstract thinking. Most programming is done with programming languages. A programming language is an artificially constructed language used to instruct computers. It is interesting that the most effective way we’ve found to communicate with a computer borrows so heavily from the way we communicate with each other. Like human languages, computer languages allow words and phrases to be combined in new ways, making it possible to express ever new concepts. At one point, language-based interfaces, such as the BASIC and DOS prompts of the 1980s and 1990s, were the main method of interacting with computers. For routine computer use, these have largely been replaced with visual inter- faces, which are easier to learn but offer less freedom. But if you know where to look, the languages are still there. One of them, JavaScript, is built into every modern web browser—and is thus available on almost every device. This book will try to make you familiar enough with this language to do useful and amusing things with it. 1
📄 Page
14
On programming Besides explaining JavaScript, I will introduce the basic principles of program- ming. Programming, it turns out, is hard. The fundamental rules are simple and clear, but programs built on top of these rules tend to become complex enough to introduce their own rules and complexity. You’re building your own maze, in a way, and you can easily get lost in it. There will be times when reading this book feels terribly frustrating. If you are new to programming, there will be a lot of new material to digest. Much of this material will then be combined in ways that require you to make additional connections. It is up to you to make the necessary effort. When you are struggling to follow the book, do not jump to any conclusions about your own capabilities. You are fine—you just need to keep at it. Take a break, reread some material, and make sure you read and understand the example programs and exercises. Learning is hard work, but everything you learn is yours and will make further learning easier. When action grows unprofitable, gather information; when infor- mation grows unprofitable, sleep. —Ursula K. Le Guin, The Left Hand of Darkness A program is many things. It is a piece of text typed by a programmer, it is the directing force that makes the computer do what it does, it is data in the computer’s memory, and at the same time it controls the actions performed on this memory. Analogies that try to compare programs to familiar objects tend to fall short. A superficially fitting one is to compare a program to a machine—lots of separate parts tend to be involved, and to make the whole thing tick, we have to consider the ways in which these parts interconnect and contribute to the operation of the whole. A computer is a physical machine that acts as a host for these immaterial machines. Computers themselves can do only stupidly straightforward things. The reason they are so useful is that they do these things at an incredibly high speed. A program can ingeniously combine an enormous number of these simple actions to do very complicated things. A program is a building of thought. It is costless to build, it is weightless, and it grows easily under our typing hands. But as a program grows, so does its complexity. The skill of programming is the skill of building programs that don’t confuse yourself. The best programs are those that manage to do something interesting while still being easy to understand. 2
📄 Page
15
Some programmers believe that this complexity is best managed by using only a small set of well-understood techniques in their programs. They have composed strict rules (“best practices”) prescribing the form programs should have and carefully stay within their safe little zone. This is not only boring, it is ineffective. New problems often require new solutions. The field of programming is young and still developing rapidly, and it is varied enough to have room for wildly different approaches. There are many terrible mistakes to make in program design, and you should go ahead and make them at least once so that you understand them. A sense of what a good program looks like is developed with practice, not learned from a list of rules. Why language matters In the beginning, at the birth of computing, there were no programming lan- guages. Programs looked something like this: 00110001 00000000 00000000 00110001 00000001 00000001 00110011 00000001 00000010 01010001 00001011 00000010 00100010 00000010 00001000 01000011 00000001 00000000 01000001 00000001 00000001 00010000 00000010 00000000 01100010 00000000 00000000 This is a program to add the numbers from 1 to 10 together and print the result: 1 + 2 + ... + 10 = 55. It could run on a simple hypothetical machine. To program early computers, it was necessary to set large arrays of switches in the right position or punch holes in strips of cardboard and feed them to the computer. You can imagine how tedious and error-prone this procedure was. Even writing simple programs required much cleverness and discipline. Complex ones were nearly inconceivable. Of course, manually entering these arcane patterns of bits (the ones and zeros) did give the programmer a profound sense of being a mighty wizard. And that has to be worth something in terms of job satisfaction. Each line of the previous program contains a single instruction. It could be written in English like this: 1. Store the number 0 in memory location 0. 3
📄 Page
16
2. Store the number 1 in memory location 1. 3. Store the value of memory location 1 in memory location 2. 4. Subtract the number 11 from the value in memory location 2. 5. If the value in memory location 2 is the number 0, continue with instruc- tion 9. 6. Add the value of memory location 1 to memory location 0. 7. Add the number 1 to the value of memory location 1. 8. Continue with instruction 3. 9. Output the value of memory location 0. Although that is already more readable than the soup of bits, it is still rather obscure. Using names instead of numbers for the instructions and memory locations helps: Set “total” to 0. Set “count” to 1. [loop] Set “compare” to “count”. Subtract 11 from “compare”. If “compare” is zero, continue at [end]. Add “count” to “total”. Add 1 to “count”. Continue at [loop]. [end] Output “total”. Can you see how the program works at this point? The first two lines give two memory locations their starting values: total will be used to build up the result of the computation, and count will keep track of the number that we are currently looking at. The lines using compare are probably the most confusing ones. The program wants to see whether count is equal to 11 to decide whether it can stop running. Because our hypothetical machine is rather primitive, it can only test whether a number is zero and make a decision based on that. It therefore uses the memory location labeled compare to compute the value of count - 11 and makes a decision based on that value. The next two lines add the value of count to the result and increment count by 1 every time the program decides that count is not 11 yet. Here is the same program in JavaScript: 4
📄 Page
17
let total = 0, count = 1; while (count <= 10) { total += count; count += 1; } console.log(total); // → 55 This version gives us a few more improvements. Most importantly, there is no need to specify the way we want the program to jump back and forth anymore—the while construct takes care of that. It continues executing the block (wrapped in braces) below it as long as the condition it was given holds. That condition is count <= 10, which means “the count is less than or equal to 10”. We no longer have to create a temporary value and compare that to zero, which was just an uninteresting detail. Part of the power of programming languages is that they can take care of uninteresting details for us. At the end of the program, after the while construct has finished, the console .log operation is used to write out the result. Finally, here is what the program could look like if we happened to have the convenient operations range and sum available, which respectively create a collection of numbers within a range and compute the sum of a collection of numbers: console.log(sum(range(1, 10))); // → 55 The moral of this story is that the same program can be expressed in both long and short, unreadable and readable ways. The first version of the program was extremely obscure, whereas this last one is almost English: log the sum of the range of numbers from 1 to 10. (We will see in later chapters how to define operations like sum and range.) A good programming language helps the programmer by allowing them to talk about the actions that the computer has to perform on a higher level. It helps omit details, provides convenient building blocks (such as while and console.log), allows you to define your own building blocks (such as sum and range), and makes those blocks easy to compose. What is JavaScript? JavaScript was introduced in 1995 as a way to add programs to web pages in the Netscape Navigator browser. The language has since been adopted by all other major graphical web browsers. It has made modern web applications possible— 5
📄 Page
18
that is, applications with which you can interact directly without doing a page reload for every action. JavaScript is also used in more traditional websites to provide various forms of interactivity and cleverness. It is important to note that JavaScript has almost nothing to do with the programming language named Java. The similar name was inspired by mar- keting considerations rather than good judgment. When JavaScript was being introduced, the Java language was being heavily marketed and was gaining popularity. Someone thought it was a good idea to try to ride along on this success. Now we are stuck with the name. After its adoption outside of Netscape, a standard document was written to describe the way the JavaScript language should work so that the various pieces of software that claimed to support JavaScript could make sure they actually provided the same language. This is called the ECMAScript standard, after the Ecma International organization that conducted the standardization. In practice, the terms ECMAScript and JavaScript can be used interchangeably— they are two names for the same language. There are those who will say terrible things about JavaScript. Many of these things are true. When I was required to write something in JavaScript for the first time, I quickly came to despise it. It would accept almost anything I typed but interpret it in a way that was completely different from what I meant. This had a lot to do with the fact that I did not have a clue what I was doing, of course, but there is a real issue here: JavaScript is ridiculously liberal in what it allows. The idea behind this design was that it would make programming in JavaScript easier for beginners. In actuality, it mostly makes finding problems in your programs harder because the system will not point them out to you. This flexibility also has its advantages, though. It leaves room for techniques that are impossible in more rigid languages and makes for a pleasant, informal style of programming. After learning the language properly and working with it for a while, I have come to actually like JavaScript. There have been several versions of JavaScript. ECMAScript version 3 was the widely supported version during JavaScript’s ascent to dominance, roughly between 2000 and 2010. During this time, work was underway on an ambitious version 4, which planned a number of radical improvements and extensions to the language. Changing a living, widely used language in such a radical way turned out to be politically difficult, and work on the version 4 was abandoned in 2008. A much less ambitious version 5, which made only some uncontro- versial improvements, came out in 2009. In 2015, version 6 came out, a major update that included some of the ideas planned for version 4. Since then we’ve had new, small updates every year. The fact that JavaScript is evolving means that browsers have to constantly 6
📄 Page
19
keep up. If you’re using an older browser, it may not support every feature. The language designers are careful to not make any changes that could break existing programs, so new browsers can still run old programs. In this book, I’m using the 2023 version of JavaScript. Web browsers are not the only platforms on which JavaScript is used. Some databases, such as MongoDB and CouchDB, use JavaScript as their scripting and query language. Several platforms for desktop and server programming, most notably the Node.js project (the subject of Chapter 20), provide an envi- ronment for programming JavaScript outside of the browser. Code, and what to do with it Code is the text that makes up programs. Most chapters in this book contain quite a lot of code. I believe reading code and writing code are indispensable parts of learning to program. Try to not just glance over the examples—read them attentively and understand them. This may be slow and confusing at first, but I promise that you’ll quickly get the hang of it. The same goes for the exercises. Don’t assume you understand them until you’ve actually written a working solution. I recommend you try your solutions to exercises in an actual JavaScript interpreter. That way, you’ll get immediate feedback on whether what you are doing is working, and, I hope, you’ll be tempted to experiment and go beyond the exercises. The easiest way to run the example code in the book—and to experiment with it—is to look it up in the online version of the book at https://eloquentjavascript.net. There, you can click any code example to edit and run it and to see the output it produces. To work on the exercises, go to https://eloquentjavascript.net/ code, which provides starting code for each coding exercise and allows you to look at the solutions. Running the programs defined in this book outside of the book’s website requires some care. Many examples stand on their own and should work in any JavaScript environment. But code in later chapters is often written for a specific environment (the browser or Node.js) and can run only there. In addition, many chapters define bigger programs, and the pieces of code that appear in them depend on each other or on external files. The sandbox on the website provides links to ZIP files containing all the scripts and data files necessary to run the code for a given chapter. 7
📄 Page
20
Overview of this book This book contains roughly three parts. The first 12 chapters discuss the JavaScript language. The next seven chapters are about web browsers and the way JavaScript is used to program them. Finally, two chapters are devoted to Node.js, another environment to program JavaScript in. There are five project chapters in the book that describe larger example programs to give you a taste of actual programming. The language part of the book starts with four chapters that introduce the basic structure of the JavaScript language. They discuss control structures (such as the while word you saw in this introduction), functions (writing your own building blocks), and data structures. After these, you will be able to write basic programs. Next, Chapters 5 and 6 introduce techniques to use functions and objects to write more abstract code and keep complexity under control. After a first project chapter that builds a crude delivery robot, the language part of the book continues with chapters on error handling and bug fixing, regular expressions (an important tool for working with text), modularity (an- other defense against complexity), and asynchronous programming (dealing with events that take time). The second project chapter, where we implement a programming language, concludes the first part of the book. The second part of the book, Chapters 13 to 19, describes the tools that browser JavaScript has access to. You’ll learn to display things on the screen (Chapters 14 and 17), respond to user input (Chapter 15), and communicate over the network (Chapter 18). There are again two project chapters in this part, building a platform game and a pixel paint program. Chapter 20 describes Node.js, and Chapter 21 builds a small website using that tool. Typographic conventions In this book, text written in a monospaced font will represent elements of pro- grams. Sometimes these are self-sufficient fragments, and sometimes they just refer to part of a nearby program. Programs (of which you have already seen a few) are written as follows: function factorial(n) { if (n == 0) { return 1; } else { return factorial(n - 1) * n; } 8