A curated list of resources on why ES6 (aka ES2015) classes are NOT awesome
Reverse-inspired by all of the awesome lists on GitHub, like Awesome, Awesome Awesomeness, Awesome JavaScript, Awesome React, Awesome Cycle.js, Awesome Go, Awesome Elixir, Awesome Elm, etc.
- Introduction
- Too Long; Didn't Read
- Reading
- Videos
- ES6 Classes in React
- People You Should Follow
- Contribution Guidelines
- License
While ES6 brings several useful and syntactically pleasing new features to JavaScript, there are many people in the JS community who feel that adding class syntax to the language was a mistake. I share this sentiment, but I have encountered quite a few programmers in the wild who don't agree or simply don't seem to understand why some of us have this opinion. So, I wanted to create an online reference where people could come to learn specifically about this issue and why they might not actually need class syntax in JavaScript.
DISCLAIMER: This is an opinionated summary of the core points made throughout the linked content. I am only providing this as a convenience for people who requested it. If you're looking for technical depth, skip this section. Please, take the time to dive into the content before drawing any conclusions.
- JavaScript is a class-free, object-oriented, & functional programming language. It eschews classical inheritance in favor of prototypal inheritance. Although it is possible to emulate classical inheritance patterns in JS, classical inheritance is not built directly into the language, and many people believe prototypal inheritance to be a more flexible and freeing paradigm due to its less rigid nature. For more, first, read this. Then, read this.
- The ES6 class syntax, constructors, the
new
keyword, etc. are ideas taken from the classical inheritance model to make programmers coming from languages like C++, Java, C#, etc. more comfortable and do not really belong in JavaScript. ES6 class syntax is essentially syntactic sugar that will end up obfuscating the true nature of JavaScript and confusing the next generation of programmers learning it. - While prototypal inheritance is very powerful in its own right, it is important to know that there is a growing movement among developers, both within and outside of the JS community (Ex: Composition in Golang), to shift away from inheritance in favor of object composition.
- Whether you choose to use prototypal inheritance, composition, or some combination of the two, you should consider using factory functions, object literals, prototypes, Object.create(), Object.assign(), etc. while avoiding ES6 classes, constructors, and the
new
keyword altogether.
If a feature is sometimes dangerous, and there is a better option, then always use the better option. — Douglas Crockford
- 10 Interview Questions Every JavaScript Developer Should Know
- Common Misconceptions About Inheritance in JavaScript
- Composition Over Inheritance
- Constructors Are Bad for JavaScript
- Delegation vs Inheritance in JavaScript
- Factory Functions in JavaScript
- How to Fix the ES6
class
Keyword - Inside the Dev Team Death Spiral
- Introducing the Stamp Specification -- Move Over,
class
: Composable Factory Functions Are Here - Javascript OO Without Constructors
- JS Objects -- Part 1: Inherited a Mess
- JS Objects -- Part 2: Distractions
- JS Objects -- Part 3: De"construct"ion
- Myth: JavaScript Needs Classes
- Prototypal Inheritance in JavaScript (Douglas Crockford)
- Prototypes Are Not Classes
- The Many Talents of JavaScript for Generalizing Role Oriented Programming Approaches Like Traits and Mixins
- The Two Pillars of JavaScript -- Part 1: How to Escape the 7th Circle of Hell
- The Open Minded Explorer’s Guide to Object Composition
- Think Twice About ES6 Classes
- Web Reflection: Better JavaScript Classes
- Web Reflection: [ES5] Classes As Descriptor Objects
- We Don’t Need a Standard for Single Inheritance. Single Inheritance Taxonomies Are an Anti-Pattern.
- Why Prototypal Inheritance Matters
- Design Patterns: Elements of Reusable Object-Oriented Software
- Eloquent JavaScript
- JavaScript: The Good Parts
- Programming JavaScript Applications
- You Don't Know JS
- Ashley Williams: If You Wish to Learn ES6/2015 From Scratch, You Must First Invent the Universe
- Atmosphere 2013: "JavaScript, the Real Bad Parts" John Paul (Conde Nast)
- Composition Over Inheritance
- Douglas Crockford: The Better Parts - JSConfUY 2014
- Factory Functions in JavaScript
- Fluent 2013 - Eric Elliott, "Classical Inheritance is Obsolete: How to Think in Prototypal OO"
- JavaScript Air Episode 01: Learning and Developing JavaScript
- Nordic.js 2014 • Douglas Crockford - The Better Parts
- Source Decoded: Composition vs. Inheritance
- Source Decoded 3: Javascript -- Prototypes, Prototypal Inheritance Done Right
Dan Abramov (creator of react-hot-loader, react-dnd, redux, and redux-devtools) has written an article on how to approach the use of ES6 classes in React in a limited & controlled way:
How to Use Classes and Sleep at Night
I'm not convinced that using ES6 class syntax in this fashion is the best long term solution for React, and you should be aware of the alternatives: React.createClass(), react-stampit, and pure (stateless) functions. However, Dan has established a solid, reasonable set of guidelines to follow in the meantime. So, if you must use ES6 classes in React, please follow his lead:
Key Points
- Resist making classes your public API.
- Don’t inherit more than once.
- Don’t expect people to use your classes.
- Learn functional programming.
Recommendations
- You can use class in your JS if you don’t inherit twice and don’t use super.
- Prefer to write React components as pure functions when possible.
- Use ES6 classes for components if you need the state or lifecycle hooks.
- In this case, you may only extend React.Component directly.
- Give your feedback to the React team on the functional state proposals.
With that said, we should think about why needing to use class
and extends
in such a limited fashion, to establish sane & maintainable practices for the specific purpose of creating a React Component (through 1-level deep inheritance), is necessary in the first place. It probably means that there should be a better solution and/or a better syntactical approach to solving this problem. I’d like to see a syntax focusing on what the conceptual thing actually is, i.e., a component, not a class… For example, why was createClass() not originally named createComponent()?
Also, read Dan's previous article on composition:
Mixins Are Dead. Long Live Composition
- Ashley G. Williams
- Github: ashleygwilliams
- Medium: @ag_dubs
- Twitter: @ag_dubs
- Dan Abramov
- GitHub: gaeron
- Medium: @dan_abramov
- Twitter: @dan_abramov
- Douglas Crockford
- GitHub: douglascrockford
- Website: Douglas Crockford's Wrrrld Wide Web
- Eric Elliott
- GitHub: ericelliott
- Medium: @_ericelliott & JavaScript Scene
- Twitter: @_ericelliott
- Kyle Simpson
- Mattias P Johansson