O'Reilly logo

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Refactoring JavaScript

Book Description

Like it or not, JavaScript is not going away. No matter what framework or "compiles-to-js" language or library you use, bugs and performance concerns will always be an issue if the underlying quality of your JavaScript is poor. Rewrites, including porting to the framework of the month, are terribly expensive and unpredictable. The bugs won’t magically go away, and can happily reproduce themselves in a new context. To complicate things further, features will get dropped, at least temporarily.

This book provides clear guidance on how best to avoid these pathological approaches to writing JavaScript. Bad code doesn’t have to stay that way. And making it better doesn’t have to be intimidating or unreasonably expensive.

Table of Contents

  1. Foreword
  2. Preface
    1. Why This Book Exists
    2. Who This Book Is For
    3. How To Use This Book
    4. Some Words in This Book
      1. App, Application, Program
      2. Inclusivity Through Words and Diagrams
      3. Users
      4. Third-Party Libraries and Communities
      5. API, Interface, Implementation, “Client Code”
      6. Inputs (Nonlocal and Free Variables)
    5. Conventions Used in This Book
    6. Using Code Examples
    7. O’Reilly Safari
    8. How to Contact Us
    9. Acknowledgments
  3. 1. What Is Refactoring?
    1. How Can You Guarantee Behavior Doesn’t Change?
      1. Why Don’t We Care About Details of Implementation?
      2. Why Don’t We Care About Unspecified and Untested Behavior?
      3. Why Don’t We Care About Performance?
    2. What Is the Point of Refactoring if Behavior Doesn’t Change?
      1. Balancing Quality and Getting Things Done
      2. What Is Quality and How Does It Relate to Refactoring?
      3. Refactoring as Exploration
    3. What Is and Isn’t Refactoring
    4. Wrapping Up
  4. 2. Which JavaScript Are You Using?
    1. Versions and Specifications
    2. Platforms and Implementations
    3. Precompiled Languages
    4. Frameworks
    5. Libraries
    6. What JavaScript Do You Need?
    7. What JavaScript Are We Using?
    8. Wrapping Up
  5. 3. Testing
    1. The Many Whys of Testing
    2. The Many Ways of Testing
      1. Manual Testing
      2. Documented Manual Testing
      3. Approval Tests
      4. End-to-End Tests
      5. Unit Tests
      6. Nonfunctional Testing
      7. Other Test Types of Interest
    3. Tools and Processes
      1. Processes for Quality
      2. Tools for Quality
    4. Wrapping Up
  6. 4. Testing in Action
    1. New Code from Scratch
    2. New Code from Scratch with TDD
    3. Untested Code and Characterization Tests
    4. Debugging and Regression Tests
    5. Wrapping Up
  7. 5. Basic Refactoring Goals
    1. Function Bulk
    2. Inputs
    3. Outputs
    4. Side Effects
    5. Context Part 1: The Implicit Input
      1. this in Strict Mode
    6. Context Part 2: Privacy
      1. Is There Privacy in JavaScript?
    7. Wrapping Up
  8. 6. Refactoring Simple Structures
    1. The Code
    2. Our Strategy for Confidence
    3. Renaming Things
    4. Useless Code
      1. Dead Code
      2. Speculative Code and Comments
      3. Whitespace
      4. Do-Nothing Code
      5. Debugging/Logging Statements
    5. Variables
      1. Magic Numbers
      2. Long Lines: Part 1 (Variables)
      3. Inlining Function Calls
      4. Introducing a Variable
      5. Variable Hoisting
    6. Strings
      1. Concatenating, Magic, and Template Strings
      2. Regex Basics for Handling Strings
      3. Long Lines: Part 2 (Strings)
    7. Working with Arrays: Loops, forEach, map
      1. Long Lines: Part 3 (Arrays)
      2. Which Loop to Choose?
      3. Better Than Loops
    8. Wrapping Up
  9. 7. Refactoring Functions and Objects
    1. The Code (Improved)
    2. Array and Object Alternatives
      1. Array Alternative: Sets
      2. Array Alternative: Objects
      3. Object Alternative: Maps
      4. Array Alternative: Bit Fields
    3. Testing What We Have
      1. Our Setup Test
      2. Characterization Tests for classify
      3. Testing the welcomeMessage
      4. Testing for labelProbabilities
    4. Extracting Functions
      1. Getting Away from Procedural Code
      2. Extracting and Naming Anonymous Functions
      3. Function Calls and Function Literals
    5. Streamlining the API with One Global Object
      1. Extracting the classifier Object  
      2. Inlining the setup Function
      3. Extracting the songList Object
      4. Handling the Remaining Global Variables
      5. Making Data Independent from the Program
      6. Scoping Declarations: var, let, and const
      7. Bringing classify into the classifier
      8. Untangling Coupled Values
      9. Objects with Duplicate Information
      10. Bringing the Other Functions and Variables into classifier
      11. Shorthand Syntax: Arrow, Object Function, and Object
      12. Getting New Objects with Constructor Functions
      13. Constructor Functions Versus Factory Functions
      14. A class for Our Classifier
      15. Choosing Our API
      16. Time for a Little Privacy?
      17. Adapting the Classifier to a New Problem Domain
    6. Wrapping Up
  10. 8. Refactoring Within a Hierarchy
    1. About “CRUD Apps” and Frameworks
    2. Let’s Build a Hierarchy
    3. Let’s Wreck Our Hierarchy
      1. Constructor Functions
      2. Object Literals
      3. Factory Functions
      4. Evaluating Your Options for Hierarchies
    4. Inheritance and Architecture
      1. Why Do Some People Hate Classes?
      2. What About Multiple Inheritance?
      3. Which Interfaces Do You Want?
    5. Has-A Relationships
    6. Inheritance Antipatterns
      1. Hyperextension
      2. Goat and Cabbage Raised by a Wolf
    7. Wrapping Up
  11. 9. Refactoring to OOP Patterns
    1. Template Method
      1. A Functional Variant
    2. Strategy
    3. State
    4. null Object
    5. Wrapper (Decorator and Adapter)
    6. Facade
    7. Wrapping Up
  12. 10. Asynchronous Refactoring
    1. Why Async?
    2. Fixing the Pyramid of Doom
      1. Extracting Functions into a Containing Object
      2. Testing Our Asynchronous Program
      3. Additional Testing Considerations
    3. Callbacks and Testing
      1. Basic CPS and IoC
      2. Callback Style Testing
    4. Promises
      1. The Basic Promise Interface
      2. Creating and Using Promises
      3. Testing Promises
    5. Wrapping Up
  13. 11. Functional Refactoring
    1. The Restrictions and Benefits of Functional Programming
      1. Restrictions
      2. Benefits
      3. The Future (Maybe) of Functional Programming
    2. The Basics
      1. Avoiding Destructive Actions, Mutation, and Reassignment
      2. Don’t return null
      3. Referential Transparency and Avoiding State
      4. Handling Randomness
      5. Keeping the Impure at Bay
    3. Advanced Basics
      1. Currying and Partial Application (with Ramda)
      2. Function Composition
      3. Types: The Bare Minimum
    4. Burritos
      1. Introducing Sanctuary
      2. The null Object Pattern, Revisited!
      3. Functional Refactoring with Maybe
      4. Functional Refactoring with Either
    5. Learning and Using Burritos
    6. Moving from OOP to FP
      1. Return of the Naive Bayes Classifier
      2. Rewrites
    7. Wrapping Up
  14. 12. Conclusion
  15. A. Further Reading and Resources
    1. Origins of Refactoring
    2. Baseline JavaScript(s)
    3. Keeping Up with JavaScript
    4. JavaScript Reference
    5. Object-Oriented Programs/Patterns (Including Anticlass Stances)
    6. Async
    7. Functional
    8. Tools
    9. Non-JS-Specific but Relevant Sources
    10. Me
  16. Index