How JavaScript Works
Douglas Crockford
Copyright © 2018 Virgule-Solidus LLC
ISBN-13 978-1-94-981500-9 Paperback.
ISBN-13 978-1-94-981501-6 Hardcover.
ISBN-13 978-1-94-981502-3 EPUB.
ISBN-13 978-1-94-981503-0 MOBI.
The computer programs in this book are in the Public Domain. The programs are provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the author or publisher be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the programs or the use or other dealings in the programs. Please use the programs for good, not evil.
This book is in the permanent collection of the world famous Library of Congress, the biggest library in the history of the planet. Made it, Ma. Top of the world!
QA76.73.J39
005.2762
Raindrops on roses and whiskers on kittens. Not Maria Augusta von Trapp
[
{"number": 0, "chapter": "Read Me First!"},
{"number": 1, "chapter": "How Names Work"},
{"number": 2, "chapter": "How Numbers Work"},
{"number": 3, "chapter": "How Big Integers Work"},
{"number": 4, "chapter": "How Big Floating Point Works"},
{"number": 5, "chapter": "How Big Rationals Work"},
{"number": 6, "chapter": "How Booleans Work"},
{"number": 7, "chapter": "How Arrays Work"},
{"number": 8, "chapter": "How Objects Work"},
{"number": 9, "chapter": "How Strings Work"},
{"number": 10, "chapter": "How The Bottom Values Work"},
{"number": 11, "chapter": "How Statements Work"},
{"number": 12, "chapter": "How Functions Work"},
{"number": 13, "chapter": "How Generators Work"},
{"number": 14, "chapter": "How Exceptions Work"},
{"number": 15, "chapter": "How Programs Work"},
{"number": 16, "chapter": "How this Works"},
{"number": 17, "chapter": "How Classfree Works"},
{"number": 18, "chapter": "How Tail Calls Work"},
{"number": 19, "chapter": "How Purity Works"},
{"number": 20, "chapter": "How Eventual Programming Works"},
{"number": 21, "chapter": "How Date Works"},
{"number": 22, "chapter": "How JSON Works"},
{"number": 23, "chapter": "How Testing Works"},
{"number": 24, "chapter": "How Optimizing Works"},
{"number": 25, "chapter": "How Transpiling Works"},
{"number": 26, "chapter": "How Tokenizing Works"},
{"number": 27, "chapter": "How Parsing Works"},
{"number": 28, "chapter": "How Code Generation Works"},
{"number": 29, "chapter": "How Runtimes Work"},
{"number": 30, "chapter": "How Wat! Works"},
{"number": 31, "chapter": "How This Book Works"}
]
Few images invoke the mysteries and ultimate certainties of a sequence of random events as well as that of the proverbial monkey at a typewriter.
George Marsaglia
JavaScript is not very pretty, but it works.
This book is for people who have had some experience with JavaScript, and want to have a better, deeper understanding of how it works and how to use it well. It is also for experienced programmers who are looking to understand the workings of another language.
This book is not for beginners. I hope to someday write a book for beginners. This is not that book. This is not a light book. If you skim it, you will likely get nothing from it.
This book is not about JavaScript engines or virtual machines. It is about the language itself and the things every programmer should know about it. This book is a radical reappraisal of JavaScript, how it works, how it could be made better, and how it can be better used. It is about how to think about JavaScript and how to think in JavaScript. I am going to pretend that the current version of the language is the only version. I am not going to waste your time by showing how things worked in ES1 or ES3 or ES5. That does not matter. The focus is on how JavaScript works for us now.
This book is not comprehensive. There are large, complex chunks of the language that will be dismissed without a word. If I fail to mention your most favorite feature, that is most likely because that feature is crap. I will not be paying much attention to syntax. I am assuming that you already know how to write an if
statement. If you need assistance with those sorts of details, ask JSLint. jslint.com
There are some useful parts of the language that I will spend little time on, such as most of the methods in the primordial prototypes. There are excellent online reference materials for that. My favorite resource is Mozilla Foundation.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
An important goal in programming language design is to produce a clean, logical language that composes well and is free of weird corner cases. JavaScript came nowhere close to meeting that goal. It gets worse with each revision as more features are agglutinated. The language is full of weird corner and edge cases. This book illuminates only a few of those corners, just to show that there are monsters there. Stay away from the corners and edges. Do not go into the dark. Stay in the part of the language that is simple and clean. Everything you need to write good programs is there.
Ten years ago I wrote a cranky little pamphlet about JavaScript. The premise was unusual, that whilst JavaScript was obviously a mess, there was buried deep inside of it a very good language. By avoiding the bad parts, you could write good programs.
This was quite at odds with the opinion of some programming experts that mastery can only be demonstrated by exploiting all of a language’s features. They believed strongly, without any need of proof, that features exist for the demonstration of mastery, so there are no bad features.
That opinion still seems to dominate even though it is deeply wrong. True mastery is shown by writing good programs that are readable, maintainable, and free of error. If you ever feel the need to show off, try doing that. Being a humble programmer, I am always looking at myself and my work, seeking to improve my skills. I have learned the hard way that optimizing for feature exploitation is counterproductive.
This is my most powerful tool for improving a programming language:
If a feature is sometimes useful and sometimes dangerous and if there is a better option then always use the better option.
So armed, I am always looking to make the language I use smaller and better, to avoid if I can the features that are more likely to create bugs. I am still refining my ideas about what is good practice and what is not. This book represents my latest thinking about JavaScript. I am able to write about JavaScript’s good parts only because JavaScript has good parts. Compared to a decade ago, I think less of the language is good, but I think that good part is better.
JavaScript has become the most important programming language in the world. That is at least partly my fault. Sorry. The issuing of new editions of the ECMAScript standard has not repaired JavaScript’s deep problems, and sometimes creates new problems. A standards committee has limited power to repair a language. They have almost limitless power to grow the language, increasing its complexity and weirdness. They also have the power to not make things worse, but where is the fun in that?
Aging programming languages suffer from a bad plastic surgery addiction. They are desperately injecting new features in the fevered hope of remaining popular, or at least fashionable. Feature bloat is as big and as deep of a problem as code bloat. I think that we should instead praise JavaScript’s inner beauty.
I also recommend that you get the ECMAScript standard. It can be tough reading, but it is free. www.ecma-international.org/publications/standards/Ecma-262.htm
Reading the ECMAScript standard literally changed my life. Like most people, I started writing JavaScript without first bothering to learn it well. I found the language to be faulty, confusing, and irritating. It wasn’t until I got around to reading the ECMAScript standard for myself that I discovered JavaScript’s brilliance.
This book about a programming language will make some people angry. I am a harbinger of the next paradigm, and that is threatening to the keepers of the old paradigm. I am used to this. I was attacked when I discovered that JavaScript has good parts, which turned out to be the first important discovery of the 21st century. I was attacked when I discovered JSON, which is now the world’s best loved data interchange format.
Communities form around shared beliefs, and communities can provide benefits to their members even when those beliefs are wrong. Communities can feel threatened when those beliefs are questioned. I am a heretic. I value the pursuit of truth over the benefits of community. That is offensive to some people.
I am just a programmer who is trying to figure out the best way to write programs. I might be wrong, but I am working really hard to get it right. Many of the patterns of thought in our profession were cemented in the FORTRAN era. I think it is time that we move beyond that. Change is hard, even in the most innovative of professions.
If you are offended by heresy, then put this book back on the shelf and walk away.
All of the code in this book is in the Public Domain. You are free to use it for any purpose, but please do not use it for evil. Try to do some good with it if that is at all possible.
I strongly recommend that you do not copy and paste code that you do not understand, even mine. This seems to have become a standard practice, but it is dangerous and reckless. It is not nearly as stupid as installing packages that you haven’t even looked at, but it is still really bad. Given the current state of the art, the most important security filter is your brain. Use it. This is important.
I make no claim that the programs presented in this book are perfect. I do claim that the programs I am writing now are better than what I was writing ten years ago. I work hard at trying to get better at this. I am hoping that I live long enough to finally get it right. I hope that you do, too. In the meantime, erratums for this book can be found at the book’s website. In Latin, the plural of erratum is errata as is done with second declension neuter nouns in the nominative case. But I am writing in Modern English, and in Modern English we should be forming plural nouns by appending –s, or in cases of excess sibilance, –es. So, yes, erratums. Given a choice between progress and tradition, I am going with progress informed by the lessons of history. That is how things are made better.
This book is about JavaScript, but I sometimes talk about The Next Language, the language that will replace JavaScript. I have to believe that there will be a language after JavaScript, because if JavaScript is the last language, that would be really sad. We must find a way to the next language, if only for our kids. They deserve a better legacy than JavaScript.
I believe that children are our future. And also robots.
The next paradigm will be globally distributed, secure, eventual programming. The Internet demands this. Nearly all of our current programming languages, including JavaScript, are still firmly rooted in the old paradigm of local, insecure, sequential programming. I see JavaScript as a transitional language. Adoption of the best practices in JavaScript will be good preparation for understanding the next paradigm.
The word for 1
is misspelled. I use the corrected spelling wun. The pronunciation of one does not conform to any of the standard or special rules of English pronunciation. And having the word for 1
start with the letter that looks like 0
is a bug.
The spelling of wun is unfamiliar to you so it might feel wrong. I am doing this intentionally to give you practice with the idea that a bad feeling about something unfamiliar is not proof that it is wrong.
This is how spelling reform happens. For example, some cat decides that it really would be better if through were spelled thru because it does not make sense that half of the letters in a popular word be silent, being wildly inefficient and putting an unnecessary burden on students of the language. Spelling reform is a struggle between tradition and reason, and sometimes, reason wins. I feel the same way about programming languages. So if wun makes more sense to you than one, then please join me in the effort.
When normal people talk about ranges, like 1 to 10, the range is understood to end with 10. But programmers often mean to to exclude the 10. This confusion is due to the common programming practice of numbering from 0 instead of 1. So I use to to mean what programmers usually mean by to, and thru to mean what normal people mean by to. So 0 to 3 mean the range including 0 1 2 whilst 0 thru 3 mean the range including 0 1 2 3. To implies <
less than and thru implies <=
less than or equal.
And whilst on the subject of whilst, in this book about programming, while is used for discussion of iteration. When discussing concurrency or simultaneity I use whilst which I take to mean while at the same time.
Both cannot and can not are acceptable spellings, but cannot is much more popular. Hasnot is not acceptable whilst has not is. And willnot is not acceptable whilst will not is. That is why I can not use cannot. But if I am in a great hurry, I can still can’t.
To my many friends for whom English is not your first language: Welcome. Thank you for reading my book. Perhaps unfairly, English has become the language of the Internet and of Software Development. Your ability to read the primary documentation directly is an important and valuable skill. I deeply respect that.
I use regular expressions. Unfortunately, regular expressions are extremely cryptic and confusing. I will attempt to mitigate that a bit by pumping lots of whitespace into them. JavaScript does not allow that whitespace, so when you seeconst number_pattern = / ^ ( -? \d+ ) (?: \. ( \d* ) )? (?: [ e E ] ( [ + \- ]? \d+ ) )? $ /;
be aware that it should be written all smushed together asconst number_pattern = /^(-?\d+)(?:\.(\d*))?(?:[eE]([+\-]?\d+))?$/;
I do not want to subject you to such unprintable ugliness, so I insert the whitespace.
In many of the chapters I will show examples of JavaScript expressions. I do that by using a special expression statement that ends not with a ;
semicolon but instead with //
slash slash followed by the result of the expression.// An example of examples 3 + 4 === 7 // true NaN === NaN // false typeof NaN // “number” typeof null // “object” 0.1 + 0.2 === 0.3 // false 3472073 ** 7 + 4627011 ** 7 === 4710868 ** 7 // true
Before the end, all will be explained.