Coffeescript in Action
Total Page:16
File Type:pdf, Size:1020Kb
Patrick Lee MANNING CoffeeScript in Action Licensed to <[email protected]> Licensed to <[email protected]> CoffeeScript in Action PATRICK LEE MANNING SHELTER ISLAND Licensed to <[email protected]> For online information and ordering of this and other Manning books, please visit www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact Special Sales Department Manning Publications Co. 20 Baldwin Road PO Box 261 Shelter Island, NY 11964 Email: [email protected] ©2014 by Manning Publications Co. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine. Manning Publications Co. Development editors: Renae Gregoire, Jennifer Stout 20 Baldwin Road Copyeditor: Linda Recktenwald PO Box 261 Proofreaders: Andy Carroll, Katie Tennant Shelter Island, NY 11964 Technical proofreader: Doug Warren Typesetter: Dennis Dalinnik Illustrator: Nick Marino Cover designer: Marija Tudor ISBN: 9781617290626 Printed in the United States of America 12345678910–EBM–191817161514 Licensed to <[email protected]> brief contents PART 1FOUNDATIONS ..............................................................1 1 ■ The road to CoffeeScript 3 2 ■ Simplified syntax 13 3 ■ First-class functions 45 4 ■ Dynamic objects 76 PART 2COMPOSITION ..........................................................105 5 ■ Composing objects 107 6 ■ Composing functions 144 7 ■ Style and semantics 179 8 ■ Metaprogramming 214 9 ■ Composing the asynchronous 241 PART 3APPLICATIONS...........................................................267 10 ■ Driving with tests 269 11 ■ In the browser 299 12 ■ Modules and builds 321 13 ■ ECMAScript and the future of CoffeeScript 353 v Licensed to <[email protected]> Licensed to <[email protected]> contents preface xv acknowledgments xvi about this book xvii about the cover illustration xxi PART 1FOUNDATIONS...................................................1 The road to CoffeeScript 3 1 1.1 Why CoffeeScript? 4 1.2 Running CoffeeScript 5 1.3 JavaScript 6 C6■ Scheme 7 ■ Self 7 1.4 Evolving JavaScript 8 A little story about language 8 ■ The lesson for JavaScript 9 1.5 Creating CoffeeScript 9 Designing new syntax 9 ■ Achieving new syntax 11 1.6 Summary 12 vii Licensed to <[email protected]> viii CONTENTS Simplified syntax 13 2 2.1 Your first program 14 Comparing CoffeeScript to JavaScript 14 2.2 Simple expressions 16 Literal values 16 ■ Variables 18 2.3 Operators 18 Essentials 19 ■ Types, existential, and combining operators 23 ■ Exercises 25 2.4 Statements 25 Anatomy 25 ■ Statements as expressions 26 Pure statements 30 ■ Exercise 31 2.5 Strings 31 Methods 31 ■ Interpolation 32 ■ Exercise 33 2.6 Arrays 33 length, join, slice, and concat 34 ■ in 35 Ranges 35 ■ Comprehensions 36 ■ Exercise 39 2.7 Heres for comments, docs, and regexes 39 Comments 39 ■ Heredocs 40 ■ Heregexes 41 2.8 Putting it together 41 Running in a browser 41 ■ Running on the command line 42 2.9 Summary 44 First-class functions 45 3 3.1 Computation 46 Basics 46 ■ Custom operations 47 ■ Anatomy 48 Comparison: JavaScript and CoffeeScript 52 ■ Exercises 52 3.2 Events 53 Browser events 53 ■ Using timeouts and intervals to create events 54 3.3 I/O 56 Ajax 56 ■ Event-driven file reading with Node.js 57 Event-driven file serving with Node.js 58 ■ Exercises 59 3.4 Higher-order functions 59 Invoking other functions 60 ■ Example: Counting words in a file 61 ■ Functions as arguments 62 ■ Exercises 65 Licensed to <[email protected]> CONTENTS ix 3.5 Scope 66 Lexical function scope 66 ■ No block scope 66 Implicit variable declarations 67 ■ Nesting 68 3.6 Closures 70 Global state problems 70 ■ Functions as return values 70 Extended example: using closure 72 3.7 Putting it together 73 3.8 Summary 75 Dynamic objects 76 4 4.1 Syntax 77 Literals 77 ■ Properties 77 ■ YAML-style syntax 78 4.2 Key-value stores 78 Data 79 ■ Key-values for named arguments 82 ■ Exercises 84 4.3 Comprehensions 85 Object comprehensions 85 ■ Example 87 4.4 Structured data 89 JSON 89 ■ Trees 89 4.5 Binding 91 this 91 ■ The fat arrow 94 4.6 Prototypes 96 Copy 96 ■ Object creation 97 ■ Exercises 98 4.7 Behavior 98 Refactor 99 ■ Exercise 100 4.8 Classes 100 Declaration 101 ■ Object identity 102 ■ Exercises 103 4.9 Putting it together 103 4.10 Summary 104 PART 2COMPOSITION...............................................105 Composing objects 107 5 5.1 Being classical 108 Raw data 108 ■ Class abstractions 109 5.2 Class inheritance 112 extends 112 ■ How does it work? 114 Licensed to <[email protected]> x CONTENTS 5.3 Class variables and properties 116 Usage 117 ■ Declaring (to keep things together) 119 Exercise 122 5.4 Overriding and super 122 Overriding 122 ■ super 123 5.5 Modifying prototypes 125 How class declarations work 125 ■ How methods work 126 Dynamic classes 127 5.6 Extending built-ins 130 Built-in constructor prototypes 130 ■ Extending date 131 Don’t modify objects you don’t own 134 5.7 Mixins 135 Class inheritance can be awkward 135 ■ Writing a mixin 136 Example: enumerable mixin 137 ■ Mixins from null 139 5.8 Putting it together 140 Exercise 143 5.9 Summary 143 Composing functions 144 6 6.1 Clarity 145 Functions are descriptions 145 ■ Where arguments need parentheses 146 ■ Higher-order functions revisited 147 6.2 State and mutability 152 Variables, assignment, and side effects 152 ■ Local state and shared state 153 ■ Encapsulating state with objects 156 World state 157 6.3 Abstraction 159 Extracting common code 159 ■ Adding common code 163 Recursion 165 6.4 Combinators 168 Compose 169 ■ Before and after 170 ■ Around 172 Working with objects 173 ■ Asynchronous combinators 176 6.5 Summary 178 Style and semantics 179 7 7.1 Rest and spread parameters 180 Rest 180 ■ Spread 181 Licensed to <[email protected]> CONTENTS xi 7.2 Destructuring 183 Arrays 183 ■ Objects 184 ■ Object shorthand 185 Array destructuring expansion 187 ■ Exercises 187 Putting it together 187 7.3 No nulls 188 Null soak 189 ■ Conditional assignment 191 7.4 No types—the duck test 193 Don’t rely on typeof, instanceof, or constructor 194 How to use duck typing 195 7.5 When to use comprehensions (and when not to) 199 map 200 ■ filter 201 ■ reduce 201 ■ Defining functions inside comprehensions 202 7.6 Fluent interfaces 203 Why create them? 203 ■ The indentation problem 205 Creating fluent interfaces 207 ■ Chain 208 7.7 Ambiguity 209 Whitespace and indentation 209 ■ Implicit variables 212 7.8 Summary 213 Metaprogramming 214 8 8.1 Literate CoffeeScript 215 The .litcoffee file extension 215 8.2 Domain-specific languages 218 External DSLs 218 ■ Internal DSLs 219 Object literals 219 ■ Fluent interfaces 221 Function passing 222 ■ Constructing a DSL 223 8.3 How the compiler works 226 Tokenizing 228 ■ Rewriting 229 ■ The abstract syntax tree 230 8.4 Bending code to your ideas 232 Can you just eval? 232 ■ Rewriting the token stream 234 Using the abstract syntax tree 236 ■ It’s just JavaScript 238 8.5 Summary 240 Composing the asynchronous 241 9 9.1 Data processing 242 Reading 242 ■ Sorting 243 ■ Performance 246 Decorate, sort, undecorate 247 Licensed to <[email protected]> xii CONTENTS 9.2 Event loops 248 Events and blackouts 249 ■ Infinite time 251 9.3 Event emitters 252 User events 252 ■ Data as events 253 ■ Using event emitters in Node.js 254 ■ Events as data 256 9.4 Event composition 257 Lazy data handling 257 ■ Lazy event handling 259 Composing event streams 260 ■ Client side 263 Multiple event sources 265 9.5 Summary 266 PART 3APPLICATIONS ...............................................267 Driving with tests 269 10 10.1 No tests? Disaster awaits 270 10.2 How to write tests 271 Assertions 272 ■ How to unit test 273 Rinse and repeat 274 ■ Feedback 276 10.3 Dependencies 278 Why dependencies make testing difficult 278 ■ Test doubles 279 Avoiding dependency injection hell 284 10.4 Testing the asynchronous 286 Live with it 286 ■ Remove it 286 ■ Expect it 287 Exercise 290 10.5 System tests 290 10.6 Test suites 291 Setups and teardowns 292 ■ Test helpers and runners 293 Watchers 295 10.7 Summary 297 In the browser 299 11 11.1 Getting started 300 Manual compilation 301 ■ Browser compilation 301 Automatic compilation 301 11.2 Communicating with the outside world 302 Using XMLHttpRequest 302 ■ Dynamic script insertion 303 Going real time with WebSocket 305 Licensed to <[email protected]> CONTENTS xiii 11.3 Cross-browser compatibility 306 Polyfilling host objects 307 ■ Polyfilling language features 309 11.4 Creating a user interface 309 Retained mode with the DOM 310 ■ Immediate mode with HTML5 canvas 311 11.5 Creating animations 314 Retained mode 315 ■ Immediate mode 315 11.6 Structuring programs 317 Abstraction and APIs 317 ■ Dealing with time 319 11.7 Summary 320 Modules and builds 321 12 12.1 Server-side modules