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