Nicholas C. Zakas — «Maintainable Javascript
Total Page:16
File Type:pdf, Size:1020Kb
Maintainable JavaScript Nicholas C. Zakas Beijing • Cambridge • Farnham • Köln • Sebastopol • Tokyo Maintainable JavaScript by Nicholas C. Zakas Copyright © 2012 Nicholas Zakas. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or [email protected]. Editor: Mary Treseler Indexer: Lucie Haskins Production Editor: Holly Bauer Cover Designer: Karen Montgomery Copyeditor: Nancy Kotary Interior Designer: David Futato Proofreader: Linley Dolby Illustrator: Rebecca Demarest May 2012: First Edition. Revision History for the First Edition: 2012-05-09 First release See http://oreilly.com/catalog/errata.csp?isbn=9781449327682 for release details. Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. Maintainable JavaScript, the image of a Greek tortoise, and related trade dress are trademarks of O’Reilly Media, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trademark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and authors assume no responsibility for errors or omissions, or for damages resulting from the use of the information con- tained herein. ISBN: 978-1-449-32768-2 [LSI] 1336581452 Table of Contents Introduction . ix Preface . xiii Part I. Style Guidelines 1. Basic Formatting . 5 Indentation Levels 5 Statement Termination 7 Line Length 8 Line Breaking 9 Blank Lines 10 Naming 11 Variables and Functions 11 Constants 13 Constructors 13 Literal Values 14 Strings 14 Numbers 15 Null 16 Undefined 17 Object Literals 18 Array Literals 19 2. Comments . 21 Single-Line Comments 21 Multiline Comments 23 Using Comments 24 Difficult-to-Understand Code 25 Potential Author Errors 25 iii Browser-Specific Hacks 26 Documentation Comments 27 3. Statements and Expressions . 29 Brace Alignment 30 Block Statement Spacing 31 The switch Statement 31 Indentation 32 Falling Through 33 default 34 The with Statement 35 The for Loop 35 The for-in Loop 37 4. Variables, Functions, and Operators . 39 Variable Declarations 39 Function Declarations 41 Function Call Spacing 42 Immediate Function Invocation 43 Strict Mode 44 Equality 45 eval() 47 Primitive Wrapper Types 48 Part II. Programming Practices 5. Loose Coupling of UI Layers . 53 What Is Loose Coupling? 54 Keep JavaScript Out of CSS 55 Keep CSS Out of JavaScript 56 Keep JavaScript Out of HTML 57 Keep HTML Out of JavaScript 59 Alternative #1: Load from the Server 60 Alternative #2: Simple Client-Side Templates 61 Alternative #3: Complex Client-Side Templates 63 6. Avoid Globals . 67 The Problems with Globals 67 Naming Collisions 68 Code Fragility 68 Difficulty Testing 69 Accidental Globals 69 iv | Table of Contents Avoiding Accidental Globals 70 The One-Global Approach 71 Namespaces 72 Modules 74 The Zero-Global Approach 76 7. Event Handling . 79 Classic Usage 79 Rule #1: Separate Application Logic 80 Rule #2: Don’t Pass the Event Object Around 81 8. Avoid Null Comparisons . 83 Detecting Primitive Values 83 Detecting Reference Values 85 Detecting Functions 87 Detecting Arrays 88 Detecting Properties 89 9. Separate Configuration Data from Code . 91 What Is Configuration Data? 91 Externalizing Configuration Data 92 Storing Configuration Data 93 10. Throw Your Own Errors . 95 The Nature of Errors 95 Throwing Errors in JavaScript 96 Advantages of Throwing Errors 97 When to Throw Errors 97 The try-catch Statement 99 Throw or try-catch? 100 Error Types 100 11. Don’t Modify Objects You Don’t Own . 103 What Do You Own? 103 The Rules 104 Don’t Override Methods 104 Don’t Add New Methods 105 Don’t Remove Methods 107 Better Approaches 108 Object-Based Inheritance 108 Type-Based Inheritance 109 The Facade Pattern 110 A Note on Polyfills 111 Table of Contents | v Preventing Modification 112 12. Browser Detection . 115 User-Agent Detection 115 Feature Detection 117 Avoid Feature Inference 119 Avoid Browser Inference 120 What Should You Use? 122 Part III. Automation 13. File and Directory Structure . 127 Best Practices 127 Basic Layout 128 14. Ant . 133 Installation 133 The Build File 133 Running the Build 134 Target Dependencies 135 Properties 136 Buildr 137 15. Validation . 139 Finding Files 139 The Task 140 Improving the Target 141 Other Improvements 142 Buildr Task 143 16. Concatenation and Baking . 145 The Task 145 Line Endings 146 Headers and Footers 147 Baking Files 148 17. Minification and Compression . 151 Minification 151 Minifying with YUI Compressor 152 Minifying with Closure Compiler 154 Minifying with UglifyJS 156 Compression 157 vi | Table of Contents Runtime Compression 157 Build-Time Compression 158 18. Documentation . 161 JSDoc Toolkit 161 YUI Doc 163 19. Automated Testing . 167 YUI Test Selenium Driver 167 Setting Up a Selenium Server 168 Setting Up YUI Test Selenium Driver 168 Using the YUI Test Selenium Driver 168 The Ant Target 170 Yeti 171 PhantomJS 172 Installation and Usage 172 The Ant Target 173 JsTestDriver 173 Installation and Usage 174 The Ant Target 174 20. Putting It Together . 177 Missing Pieces 177 Planning the Build 178 The Development Build 179 The Integration Build 180 The Release Build 180 Using a CI System 181 Jenkins 181 Other CI Systems 184 A. JavaScript Style Guide . 185 B. JavaScript Tools . 205 Index . 209 Table of Contents | vii Introduction The professionalization of web development has been a difficult journey because of our disparate beginnings. Even those who end up at large companies such as Yahoo! in- evitably began on their own, hacking around. Perhaps you were even “the web guy” at a small company and could do pretty much whatever you wanted. When the large companies started tapping this previously undiscovered resource, it brought a lot of hackers into a corporate environment, where they were met with constraints. No longer a lone soldier in a small battle, all of these self-taught, self-directed individuals had to figure out how to work within a team environment. I learned JavaScript the way many did in the late 1990s: I taught myself. Because Java- Script was so new, educational resources were scarce. I, like many other developers, learned by exploring the intricacies of Internet Explorer and Netscape Navigator on my own. I experimented, theorized, and experimented again until I discovered how things worked. Luckily for me, this curiosity and diligence turned into my first job. For the first five years of my professional career, I was “the JavaScript guy.” No one in either of my first two companies could match my depth of knowledge in JavaScript and web development in general. All problems, from very simple to very difficult, ended up on my desk to solve by myself. It was both empowering as a fresh-from-college kid and terrifying because I had no one to bounce ideas off of or anyone to ask for help if I got stuck. I did the best that I could, knowing that I was the only one who could do it. During those five years, I honed my craft. I came up with ways of doing things that made sense to me and my workflow. I didn’t have to worry about what anyone else thought of my code, because no one had enough knowledge to code review or fix what I had written. I was a hacker in its purest sense: I wrote code the way I wanted and wouldn’t hear of changing it. In year six of my professional career, I switched jobs and ended up on a team where everyone was expected to contribute code in all aspects of the project. No longer able to focus on JavaScript and web development, I found myself writing server-side code and SQL queries most of the time. Meanwhile, traditionally backend-focused devel- opers were being forced to write web code. This experience really opened my eyes: the ix way I used to write code wasn’t the way the rest of the team wrote code, and that was a problem. I quickly realized that to be more effective on the team, I had to start writing code the way the rest of the team wrote code. Server-side code and SQL were a bit alien to me, so I adopted the patterns of those around me who knew what they were doing. At the same time, I started talking to the other engineers about adopting coding patterns for HTML, CSS, and JavaScript. I even added JavaScript linting into the build process to enforce our standards—the first test of web code ever at the company. And soon, the team was working as a well-oiled machine. When I arrived at Yahoo! in 2006, I came with a specific idea of how things should work when I got there. What I found was a completely different animal altogether. The My Yahoo! team, the first team I worked on, was much larger than any I had worked on before. There were already pseudoguidelines in place, and I had a lot to learn. New technologies, new processes, and new tools were presented to me on a daily basis. I was overwhelmed and resigned myself to spending some time learning about this new environment and soaking up as much knowledge as I could from my colleagues. After a few months, I started to find problems.