This is my favorite book about JS, and I always recommend it to people. It occurs to me for the first time that the lack of TypeScript might be a problem, because if I’m making recommendations to someone learning, I am definitely going to recommend they write TS instead of JS. On the other hand it may actually be helpful to learn the concepts in this book without the additional syntax overhead of type annotations, plus the more webby content doesn’t really have much to do with types anyway.
This is, in my opinion, the book to use to learn JavaScript at more than a surface level. The only other materials I recommend as much (but for a different level of learner) are the “You don’t know JavaScript” in-depth book series.
In 2015, I was consulting for a distance learning program, administered by a major California University, that wanted to replace their current textbook (one of those “Head First” O’Reilly books) with something that had a bit more meat but was very approachable. I immediately recommended this and it was fawned over by both the advisors and instructors. It was also the cheapest option they had in the running (even excluding the fact it can be read for free) as it was competing against traditional text books. One year later, students were polled on it and it was met with a lot of positivity as well.
+1 for "You don't know js", it's a must read for any js programmer IMO.
I haven't read eloquent JS though, you say it's a different level of learner. Can you expand a bit? Is Eloquent for after "you don't know js" or vice-versa?
Edit: nevermind, reading the TOC of eloquent JS gave me a good enough idea
I get so jealous that people can absorb information via books as an adult. I can read the same chapter a hundred times and nothing sinks in.
I know this is off topic but do you, or anyone passing, have a system or tips for how y'all do this? I've got so many programming books but they only collect dust after I read through them without benefit.
Are you reading programming books the same way you would read a fiction book? If so, stop doing that.
Programming or any technical learning is a hands on experience. Take notes and apply techniques, using pen-and-paper or the keyboard, as they are presented.
If you really have to just "read" a technical book, IME a less-is-more approach works best. 5-10 minutes at a time, not even a chapter at once. Maybe a few paragraphs if its something really information dense. Funny aside, I find my morning "business" is the perfect time to this sort of reading using the Kindle app on my phone.
I read about fifty books a year for a decade now. Only about four of them per year, are programming books. They are indeed to be read very differently. Here's how I read them, ymmv.
- never in bed. never as audiobook. But sitting. At a table or desk.
- no distractions. At most "focus music".
- read a chapter through. Then read it again and do all excercises (on a computer without wifi)
- make copious notes, highlight quotes, summarize. Most important for me is to write down why I made that note.
- a time (years sometimes) later, do it again. E.g. when having worked on the concepts from a book in real prod projects.
- at most an hour. I have ADHD and my mind often flies everywhere suddenly; time to give up and grab a beer or coffee.
Very few of these work as ebook (Kobo) for me. The formatting of code is poor and diagrams unreadable. Prefer paper or PDF (but read on a computer or tablet without network).
I don’t mind distractions when learning via books (I wouldn’t be able to finish my degree otherwise), but the other advices still apply. Reading a chapter without doing the exercices is like listening to a lecture without taking notes. You may understand a few things (or everything), but you’ll find that doing practice, drawing diagrams, or summarizing it lead to a deeper understanding. More often than not, you have to dedicate a few days or weeks depending on how dense it is. You find yourself rereading a page from a previous chapter or consulting another book. You don’t have to read it end to end unless you view it as taking a course.
Disclaimer: this is my own, metaphor-filled hypothesis.
It’s easy to fully internalize generalizations that someone has presented to you, usually because it’s wrapped up in a way that is mostly compatible with how you see the world. Because someone has done the work of distilling this information, you are not able to share in most of the intellectual benefit. It’s the process of having a question, discovering an answer, internalization of the concept, and synthesizing a summary that brings you closer to understanding. It feels like a series of “lightbulb moments” when we consume this content, but it is often shallow and fleeting because the genesis of the idea was not your own. Airport/self-help books are a good example of this mental candy that makes us feel good when reading it but, unless you are able to fully internalize it, are just empty mental calories.
Comprehension and understanding are derived from amassing knowledge a little bit at a time as your mind is ready to advance your understanding. In other words, you really have to be “primed” for knowledge found in books. This is the reason that information you obtain after an adequately-informed struggle stays so salient: your mental model had all the scaffolding around a concept but there was a clear “void” where this answer fits, and if you find that fits super cleanly, it’s extra satisfying.
When consuming information-dense material, you end up with this knowledge back-pressure where it’s floating around your short term memory but won’t be committed to long term memory because there is just no place for it yet. When recalling information in order to create new content with it, and assuming you are challenging yourself, you will end up in situations where there is information starvation (the opposite of back-pressure) where you must either find answers (to fit in your mental model) or find a workaround (ignore the gap).
Some people can just read books and create efficient mental models. Others (myself included) have a limit of how much they can learn in one sitting because our brains need to be fully ready to accept this information.
The last piece of this is the dopamine response cycle that is a positive feedback system (positive as in “more creates more”). Dopamine makes us feel good by rewarding behavior that evolution deemed necessary for species survival (over simplification). Dopamine indirectly triggers long term memory retention because we need to remember why we felt good in that moment so we can replicate it. This used to be, “this berry tastes good, I should remember where this bush was and what the berry looked like.” In the modern context, it ultimately delivers motivation to us because we have adapted to using it to learn new information that is less relevant to survival. Achieving goals and solving problems at hand causes a huge amount of dopamine release. The problem is that we’ve found ways to hijack these systems and short-circuit this feedback cycle so everything had to become way more stimulating.
This got long, but my advice is to work on a project of your choosing that you are intrinsically motivated to do. Begin work on that project and read some of the book that relates to the problem at hand. Repeat this cycle of reading and working, trying to incorporate patterns and concepts you find while reading into your project. Make little goals for yourself every day before your start, and really hold yourself accountable in finishing them.
What I like to do, when not under time pressure, is to read such a book cover-to-cover, as a first pass. I get an idea which parts will be difficult for me, and which are probably not.
In this stage, I don't sweat the parts I don't get, I just note for later, that, if these turn out to be important, will require some care, patience and time. I also build some sort of "map" in my mind about the elements that exist, to get an overview.
After doing so, I feel a lot more confident to tackle the topic of the book "properly", doing exercises, etc.
Take notes as you go or by chapter. If a chapter has a summary at the end, read that first before going through the chapter. If there are code examples, write them out and play around with it. Get the important bits out that way.
Also, realistically you probably won't remember most of what you read. I suck at that as well, but you do build up a lot of peripheral knowledge. You may not remember how to do that one thing, but maybe you do remember that it exists, or that it was in a particular book. Just that type of knowledge has worked well for me.
Not the original poster, but I learn best reading textbooks cover-to-cover. A couple things that help me:
1) I buy physical textbooks and absolutely destroy them with notes in the margins, highlighting, etc. It helps me to interact with the material instead of letting it wash over me, which means I'm both thinking about it more in-depth and as side effect I'm less bored. Otherwise I'll fall asleep and won't learn anything. 2) I accept that I'm not going to remember the entire book. A lot of books are most useful as references anyway. But if you ever find yourself going, "Oh that's really handy to know," then you can make a special note of it or even put it into flashcards. I've been using Anki. The trick is to recognize what is actually worth doing this for. 3) If something is especially worth knowing, (see point 2), see if you can either do problems from the book or try out the concept in some way if there are no problems available.
If you're reading something just because you feel like you should, you won't get anything out of it (or a least I don't).
Everyone has different learning styles. I retain maybe 90% of what I read, but only 10% of what I hear. So videos and any audio are the worst formats for me to learn anything.
The first step is figuring out what your learning style is.
1. Take notes. If you are reading an ebook or a webpage, handwritten notes may be better because you will not be tempted to copy and paste.
2. If feasible for you, consider getting a neuropsychological evaluation to rule out any learning disabilities like adult attention deficit disorder.
yes, also javascript the good parts is really good(hehe) because it's more theoretical and there is not html or web stuff in it just the language
How recently have you read it? I thought it was a worthwhile read when I first read it 12 years ago, but I picked it up to skim a couple years ago and was struck with how much of it was irrelevant for modern JS due to changes in the language spec.
In that sense an annotated "this is what JS used to be when this book first came out" version could be of historical interest.
Last time was 2017 I think, don't know if there is a big difference I use both new and old things
One hundred percent agree on both this book and the “You don’t know JavaScript”. Both are free (search Kyle Simpson GitHub). I ended up buying the YDKJ first edition paperbacks but see the second edition of all of them are done or a work in progress. EJs is the one I tell my students to start with as IMO is more of a programming book that just happens to us JS. I can tell the ones that read it (it’s optional) and the ones that do not. I do a few random chapters every year and learn something that I either missed or forgot I knew every time. I am mostly using TS these days but also enjoy vanilla JS for side projects and prototypes. Note the YDKJ books can come off as very ‘only my opinion is the right one’ kind of like JS the good parts but just look past that and absorb the content, what you do with it after that is up to you regardless of the author’s opinion.
YDKJ 2nd edition after first two parts the rest seems less actively worked on? hope the 2nd revision will be done soon.
I think Kyle Simpson is out of work and looking for something full-time and also started some other company, so probably not his main priority atm.
I second JavaScriptInfo as another great resource to learn JS: https://javascript.info/
I agree
If you want a video series that accomplishes a lot of the content in these books it's Will Sentance's Javascript: The Hard Parts.
Cheers Josh :)
I remember reading the first edition back in maybe 2011 when I decided I should sit down and actually learn JavaScript beyond the superficial grasp I had of it from working on web things (mainly via Rails at the time). What a great book, I learned so much from it at the time. For years after, whenever anyone told me they wanted to learn programming, I told them to pick up this book as a first introduction to it. Plus, it was available for free on his website.
I've gotten rid of lots of old programming books over the years, but I've held on to my first edition copy of Eloquent Javascript. Lots of thanks to Marijn for writing this!
I love this book, even since its first edition. It's very clear even on elementary stuff, e.g. see the section on bindings/variables: https://eloquentjavascript.net/02_program_structure.html#h-l... — avoids the pitfall of thinking of variables as “boxes”.
I was trying to find what's new in the 4th edition, and following links from the author's website https://marijnhaverbeke.nl/ found this on Mastodon (https://mastodon.social/@marijn/112020092273623390):
The FOURTH EDITION of Eloquent JavaScript is now online, adjusted to the realities of 2024 and generally touched up.
It's a great explanation, but I've never heard the term 'binding' used to describe variables. It's usually reserved to function binding or bridge APIs like the DOM.
The tricky thing is that "boxes" are the right abstraction for primitive values. After that you need to explain how references work, and that's pretty much the same 'tentacle' concept. This method spares the reader one step, but might cause confusion once they face problems that require that understanding.
"binding" is a PLT term, denoting the association between a name and a value.
It's a higher level concept than the variable - a mutable binding is what people usually refer to as a variable, and an immutable binding is the correct term for what people refer to an "immutable variable" (an oxymoron, if you think about it).
Immutable variable isn't a oxymoron. It can still vary between instantiations. If you have (a)=>{const b = a}, b can have different values even though it can't be reassigned.
In the case of the code that you have cited, these are all different elaborations of the binding at the invocation of the lambda, due to the interplay between activation records and scope rules.
It's not really an "immutable variable" - it's a local binding getting bound to different values on each scope entry.
EDIT: By the way, the `b` binding in your code can be modified. Did you mean `const b = a;` ?
it's a local binding getting bound to different values on each scope entry.
It is, I just wanted to point out that the term "immutable variable" is sensible. I think a good way to put it is that b is a variable, and when the statement runs a value is bound to b. So the value bound to b varies yet b can be immutable, in contrast to a constant which is a binding to always the same value.
Did you mean `const b = a;` ?
Fixed, thanks :)
"binding" seems like a more casual term for memory pointer. I guess if people are just getting started with programming it make sense to simplify things a bit.
My point is that it's not a simplification, it's precisely how the language works: bindings between values and names (JavaScript has no separate notion of memory pointer; everything is a "pointer"). (Similarly for Python: https://nedbatchelder.com/text/names1.html) Describing variables in this way gives readers the correct understanding, and the analogy of tentacles is no harder than that of boxes. Such things are what I most appreciated, that the author manages to be approachable without sacrificing accuracy.
It's not a simplification. It is abstraction. Binding doesn't imply a particular implementation.
A variable binding can disappear entirely. If you bind var x = 42 and never use it, the variable need not exist. If it doesn't exist, then there is no pointer.
If you do use it, constant propagation/folding can again make the variable disappear. If the variable is never assigned, all uses of it can be replaced with 2.
Variables that care captured by lexical closures can be treated differently from ones that are not. Variables captured by closures but not shared among different closures, or not mutated, can be treated differently from mutated variables shared among closures.
The abstraction of binding is more complicated than "every variable is a memory pointer" because it allows more possibilities, which can coexist.
"binding" is pretty standard terminology in some oldtimey languages; lisp, ML, etc.
Bash documentation says that "set -u" traps variables that are "unset".
The actual diagnostic itself is better educated:
$ set -u
$ asdasdf
$ echo $asdasdf
bash: asdasdf: unbound variable
"Binding" is used thousands of times in the language standard, including for variables: https://tc39.es/ecma262/#sec-variable-statement -- that's my point, that this book is precise while being approachable to beginners.
And I dispute the claim that "boxes" are the right abstraction for anything in JS. (Boxes may work for primitive values, but nothing further.) Directly seeing names as bindings ("tentacles") not only skips the incorrect "boxes" step, but also causes no confusion or problems whatsoever at any point. (If you have an example, I'd be curious to see it.) (There are some differences in the language between primitive values and Object, but none of them are particularly helped treating variables as boxes AFAICT.)
1) the most common binding used in well written modern JavaScript is a const binding. It is by definition not a variable.
2) the ‘binding/tentacle’ metaphor works just fine for primitives and the ‘boxes’ model adds more complexity.
I'm curious - could you expand on why it's a pitfall to think of variables as boxes?
Because that's not how variables work in JavaScript/Python etc (though it may be fine for say C++ in the case of value types and copy constructors). For example:
I'm typing on phone so for a quick example:
let a = [];
let b = a;
a.push(1);
and consider the value of b now (or the fact that we could write "const" above because the binding is constant, even though we mutate the value). Or see the equivalent for Python by Ned Batchelder, which has more examples and elaboration: https://nedbatchelder.com/text/names1.htmlI knew that in Python all variables are really references to objects (even when we're using a number) - is JavaScript the same way?
Also, does anyone have a link/reference to the place in the spec where it specifies this? I briefly skimmed through parts of [1] but couldn't find anything that says that JavaScript treats numbers this way.
As I understand it, JavaScript does have a distinction between the primitive types and Object, but this does not show up in any significant way to the programmer / in any way relevant to how to view variables. To put it differently, the "boxes" view only applies to primitive values, while the "tentacles" view applies to all values, so the former is unnecessary and need not even be considered/taught.
The book is actually maintained on GitHub too, https://github.com/marijnh/Eloquent-JavaScript.
When I was just starting out I read this book and noticed a small mistake, I was really proud that one of my first contributions to any open source project was a PR to this repo.
Thanks, that gives a way of seeing the diff between the third edition and the current (last commit 45 minutes ago): https://github.com/marijnh/Eloquent-JavaScript/compare/f8f00...
Looks as if there will still be a paperback version released in the future as well for anyone that prefers that format.
I don't work in JS at all professionally but this book has intrigued me for a while at this point after seeing it recommended so often. I think I'll pick up a copy once the paperback is released.
Someone asked about integer support in JavaScript. JS now supports BigInt!
>2**57
144115188075855870
>2n**57n
144115188075855872n
And in some JavaScript engines (eg V8) bigint multiplication is asymptotically fast, unlike say the default CPython. It’s a very pleasant surprise if you happen to be a number theorist (say).
That's news to me!
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Oh thank god.
I've been having to do some hacky things to represent numbers on an astronomical scale for my star system/planet generators.
Yes, I was asking about that and I'm very happy to see this exists now.
I don't mean to throw shade on the whole book, but I don't think the section on errors takes things in the right direction.
A distinction should be made between errors and exceptions. In JavaScript and many languages, we conflate the two and use exception handling as logic flow control. In my experience, this can end up being a headache and encourage unnecessarily weird structuring of code.
Look at this example from the page on errors:
---
function getAccount() {
let accountName = prompt("Enter an account name");
if (!Object.hasOwn(accounts, accountName)) {
throw new Error(`No such account: ${accountName}`);
}
return accountName;
}---
The possibility that a user will enter a account name that doesn't exist is not an exception, but we are treating it like one in this case. In order to handle this exception when getAccount is called, we have to wrap it or some higher level scope in a try-block and then regex-match the error message if we want to handle it differently from other errors.
You might be saying "it's just an example", but there's plenty of production code in the wild that is written this way. Maybe this could be improved by subclassing Error, but now you're having to manage a bunch of clutter and using object-oriented features as a way to reliably determine what kind of exception you're dealing with.
I find this pattern to be preferable:
---
const ACCOUNT_NOT_FOUND_ERROR_CODE = 1;
function getAccount() {
let accountName = prompt("Enter an account name");
if (!Object.hasOwn(accounts, accountName)) {
return {
accountName: null,
error: {
code: ACCOUNT_NOT_FOUND_ERROR_CODE,
message: `No such account: ${accountName}`,
}
};
}
return { accountName, error: null };
}---
Then we can call the function like this:
---
const { accountName, error } = getAccount();
if (error) {
if (error.code === ACCOUNT_NOT_FOUND_ERROR_CODE) {
errorModalService.show(error.message);
}
} else { // do something with the account name
}---
No doubt, you may still want to catch exceptions at a higher level scope, but at the nice thing here is that exceptions (almost) always represent actual unexpected conditions that aren't being handled properly while return values with error codes represent expected conditions and can be handled like any other logic in your code. It also reduces any ambiguity of how an error should be handled but without subclassing. An error can even contain more information than just a message if you want it to.
Also, if you really want to ignore an error for some reason, then you can just pretend that the error doesn't exist. No need to use a try-catch where the catch-block is a no-op.
I wish we'd encourage this sort of pattern, but maybe that's one of many pipe dreams of mine.
1. Exceptions can have codes, too, you know, and often do. 2. In the example, the exception is meant to bubble up all the way to the consumer. Different consumers can then handle as they see fit, even just displaying the exception message to the user.
Yes, exceptions can have codes. As far as I have experienced, their error instances don't do anything better than a plain object, and a non-exception error object can more clearly take a wide variety of shapes. It also limits potential confusion between errors or exceptions raised by your code and that of some dependency.
It is true that exceptions "bubble", and plenty of developers take advantage of that behavior. In my opinion, it is not helpful for errors that are expected to happen as part of normal application behavior. Bubbling of errors creates a sense of logical indirection. Errors as return values communicate that likely nothing " wrong" actually happened. Good communication through code reduces the amount of time developers spend using the wrong assumptions when debugging.
There is also no reason why errors in a return value can't be returned by the caller. When you learn to love objects/hashes as return values, you can get the same benefits of bubbling but with a more clear path to follow when getting a picture of where a value is coming from and why.
In the case of actual exceptions, like accessing a property on undefined, an error being thrown is appropriate because, like you say, it can be bubbled up. The nice thing about reserving exceptions for this sort of thing is you might get away with a single try-catch at the highest scope and have a single straight forward error modal for when an unexpected problem occurs. Then you can otherwise implement errors in your code without the possibility that they will escape through bubbling and trigger behavior that is not immediately obvious when following the path of execution.
This is not to say that the tradition of using errors and try-catch for normal application control flow is inherently bad. Its just another tool. I do subjectively believe they are counter productive when used that way, and encourage others to try something like my approach. I think we would benefit by making it a standard practice.
In other languages like Java this can work because of checked exceptions (can work, I know there are a lot of mediocre devs who don't know what to do with checked exceptions but that's another issue). But in JS this is a terrible way to deal with any problem that can be handled.
I'd agree, but incidentally I've also been extracting string labels into some higher level, such as a constant or message creator function that looks up the message by it's code in some dictionary. It helps with readability, particularly in modern view libraries, to just have all your labels in one place and not have to scan the JSX or HTML for the string literals, and likewise all modifications will produce more concise diffs, testing could be easier if you're doing string matching, localization is more manageable with fewer scattered external dependencies on translation hooks or w/e
What's new in this edition?
It should be mentioned in the "Introduction" but it seems your question is not covered there.
Could've used better commit messages, but:
https://github.com/marijnh/Eloquent-JavaScript/compare/3rd_e...
you can see the differences on github: https://github.com/marijnh/Eloquent-JavaScript/compare/3rd_e...
From a quick browse:
- # for private properties
- ESM imports in node
- hasOwnProperty -> hasOwn (TIL: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...)
- Math.pow -> **
- coverage of `function*` generators (https://eloquentjavascript.net/11_async.html#h-o+cFzGGhnz)
Here's a diff without the first commit that changed all linebreaks: https://github.com/marijnh/Eloquent-JavaScript/compare/d8290...
this book taught me javascript! great book, highly recommend it.
I agree. Have you also read "JavaScript: The Good Parts" ?
nope, looks like a deep cut and will fill in some knowledge gaps i have. thanks for the rec.
another good one for my learning was "secrets of the javascript ninja"
Secrets of the Javascript Ninja is my favorite JS book by far.
"JavaScript: The Good Parts" was a great and a very important book back in the day. I am sure it inspired many of the improvements JavaScript has seen since then. But as it has seen these improvements, and as they were many indeed, I am not sure the book is still as relevant as it once was. Or to put it differently: There are many more good parts to JS these days compared to when the book was released :)
What if one is using TypeScript?
The rules still apply.
I'm currently going through a hard copy of the book's third edition. But I'm wondering whether the description of the language in the book is detailed enough. Could you share some opinions on whether it will be good to go through some other JavaScript books after it? I'm considering going through "JavaScript: The Definitive Guide"[1] or "The Modern JavaScript Tutorial"[2] after it.
[1] https://www.amazon.com/JavaScript-Definitive-Most-Used-Progr...
"JavaScript: The Definitive Guide" does go deeper, with thorough examples in all the topics mentioned in the index. It also provides examples of static types using Flow instead of TypeScript.
Fancy seeing this here, some days after finishing the third version :)
I'm also glad to see the asynchronous programming chapter significantly reworked - it was materially weaker than the rest of the book because of some weird analogies involving crows and their nests that didn't seem to make any sort of sense to me.
The third edition also gave me the impression that it was a reasonable book to learn JS and the DOM (and a sprinkle of Node.js, for good measure), but that it was a book aimed primarily at experienced people who were transitioning to JS and the web - not beginners (despite the book's efforts at claiming suitability for beginner programmers).
book because of some weird analogies involving crows and their nests that didn't seem to make any sort of sense to me.
I am glad I am not the only one. I believe he over-abstracted it to it's own detriment.
I went to purchase a paperback earlier this week. Now I will wait for this one to hit print.
For those that don't know the author, Marijn Haverbeke is the creator of CodeMirror (code editor) and later ProseMirror (text editor).
The field of programming is young and still developing rapidly, and it is varied enough to have room for wildly different approaches.
This was an interesting line of thought to digest. He's right, of course. Programming is probably still in it's infancy.
Studying and learning about programming however, can make you believe it's some ancient art mastered by the giants of our recent past, the perfection of which is never to be surpassed again.
https://arc.net/boost/3098D5E3-F164-478B-9586-077889192460
The 'Eloquent JavaScript 4th edition (2024)' in Dark Mode
Great book, looking for some info about main changes from 3rd edition but did not find it.
How does Eloquent JavaScript compare with Horstmann‘s JavaScript for the Impatient?
Definitely one of my favorites. It helped me level up when I was learning Javascript but also helped me understand how to be a better programmer.
This is the book that helped me really understand JavaScript. Really great content and I can't thank Marjin enough for putting this out there for free.
Also how this person is so productive? I really would love to read on how he manages his time and priorities.
I have Zakas' Professional JavaScript for Web Developers and ECMAS 6 update. Was very happy with them (easy to read) but both are getting long in the tooth and the author seems to have lost interest in updates.
How does this one compare as an all-in-one? Being up to date is a win, but I'm wondering about the quality of the writing.
When is the print book coming ?
I wonder if such high quality free books are already fed to LLMs during training?
Chapter 11 on async is particularly good, I still get confused by async/promises sometimes in Javascript - https://eloquentjavascript.net/11_async.html
test
The best JavaScript book out there, IMHO
Part of the force of this book comes from its explanation of fundamentals of computing, and how it relates to javascript. Another part is due to how interesting are the projects that it proposes that the reader build. I don't even like programming in javascript but was drawn to read the book.
Great book
I don't consider myself a good programmer. I struggled throughout my youth to grasp even the basics. This book pointed me in the right direction. Can't recommend it enough.
Sounds like a joke, an oxymoron.
The one odd thing in it is that it still claims SVG markup needs a namespace. Which it doesn't, SVG became part of the HTML5 spec and emphatically should _not_ use namespaces when used as "just another element" inside an HTML document.
(even though you do need a namespace when creating svg elements through createElementNS, both "of course" and "unfortunately", and of course you need namespaces if you're creating an actual stand-alone SVG document)
Why is that? If you want them to learn JS, teach/recommend them to learn JS?
Compile-to-JavaScript languages come and go, but JavaScript has remained. First learning vanilla JavaScript makes sense, and then add TS on top if you really have to. At the very least they'll be prepared for when TypeScript goes out of favor.
Because TypeScript is the de facto standard way of writing JavaScript for most of the industry and it has killed all of the other compile-to-js languages.
The chances of it going out of favour are very slim, there's a giant ecosystem built on it and the language is very well loved by devs (should be second only to Rust).
Microsoft has 50 people on payroll working only on TS. Any competitor needs a gargantuan investment.
And JavaScript has a bigger ecosystem and more entrenchment, not to mention an international standard.
Not sure how's that relevant.
Any valid JavaScript is valid TypeScript and you're gonna write and read TS anyway in the industry.
They aren't in competition, but coming back to the first comment it sounds reasonable to start directly with TS for many users.
Your experience is not the industry. JS is widely used, almost certainly more than TS.
My experience may not, but the annual JS dev survey points that TS is the main way to write JS from years.
and not to mention terrible.
Flow has about a dozen of important features that typescript lacks (while being 10x smaller in terms of LoC).
Flow is basically a dead project outside of Facebook.
https://npmtrends.com/@babel/preset-flow-vs-flow-bin-vs-type...
Not that I think download metrics is the best metric to decide that, but even with that, flow-bin has almost half a million of downloads per day. That's far away from dead, at least in my world. And I'm guessing that doesn't count anything from Facebook as they most likely run their own registries.
flow-bin has substantially fewer downloads than coffeescript and both are declining. That is a dead project.
https://npmtrends.com/coffeescript-vs-flow-bin
I use TS, I like it.
I'm not sure you're 100% right about it overtaking JS for most of the industry.
I wouldn't recommend it to beginners until they've learned JS because it's a lot of stuff to learn on top of JS to achieve basically the same outcomes (with fewer bugs). Chapter 5 in the Eloquent JavaScript book gets to higher order functions, which in TS means Generics. Nobody needs to learn Generics in Chapter 5 of their programming journey.
You also don't really appreciate how useful TS is until you've battled at least one project in plain JS.
(Arguably you can go a long way without HoF too, but perhaps not if you're hoping to understand other people's code.)
Technically Haxe is still a thing, though its typical use case these days is almost 100% game development (including the JS target).
It really isn't, but I guess that's really context specific. What country and sector are you talking about? For US-SaaS, what you're saying is probably true, but there is a whole world outside of that, and JavaScript is with 99% certainty much more wildly used than TypeScript.
Also it hasn't. I've been writing ClojureScript for the last 5 years, almost exclusively. And while the community is small, I wouldn't say it's "dead" or been killed. There are a bunch of compile-to-JS languages that haven't "been killed", besides ClojureScript.
But it serves basically the opposite niche compared to TypeScript.
Same has been said about everything, always, and it's always not true. Winds change, and surely so shall the winds of TypeScript. Not being able to see that it's possible, will put you at disadvantage.
TypeScript isn't really a "compile-to-JavaScript" language in the same way that, say, Rescript is. Modulo a few corner cases (e.g. enums) which are now considered anti-features, TypeScript has the exact same runtime semantics as JavaScript - you can (almost) convert TypeScript to JavaScript just by stripping away the type annotations (and, if various ECMAScript proposals go through, you won't even need to do even that).
This is both a curse and the secret behind its success - it's arguably not a separate language, but instead an annotation layer on top of the existing language for encoding and checking your static reasoning and assumptions.
I guess by that same definition, Coffeescript isn't a compile-to-JavaScript language either, as it has the same semantics as vanilla JavaScript?
I think that's besides the point. My point was more that people who are supposed to learn JavaScript, should do so by learning vanilla JavaScript first, then they can move on to learning whatever is currently hyped by the zeitgeist (which happens to be TypeScript currently).
No, CoffeeScript doesn't have the same semantics as vanilla JavaScript; not in any meaningful sense I can think of, certainly not in the way that TypeScript does.
Most CoffeeScript will simply syntax error if you feed it into a JS interpreter (and vice versa), and there's no trivial syntactic transform to get around that (i.e. it's not just a new surface syntax over JavaScript). Various features in CoffeeScript have no equivalent in JS, so new code needs to be synthesized for them; even fundamental features that are shared by the two languages are different - for just one example, this [0] article shows that how a function is compiled in CoffeeScript is non-local - the compiler is tracking variable scopes to get around the fact that CoffeeScript and JavaScript have different scoping semantics.
With TypeScript, the "compilation" process is (almost):
That's it! TypeScript code is syntactically valid JavaScript code, just with added type annotations (and, as mentioned, soon that'll still count as syntactically valid JavaScript code); JavaScript code is syntactically valid TypeScript code without any type annotations - which doesn't make it syntactically invalid! Indeed, if you turn down the strictness settings on tsc to permit untyped code, the compiler doesn't even complain about it.[0] https://donatstudios.com/CoffeeScript-Madness
CoffeeScript has quite a lot of code generation features, while TypeScript largely just removes code in order to transpile to JavaScript. The only exception I can think of is enums, and I suspect they wouldn't have put those in if they had it all to do over again.
Which further exposes the irony of casual hipsters who say things to me like "Thank God for Typescript, it's like a whole other language than JS". For example, a designer, who writes a quick one off plug-in for Figma in Typescript without realizing 99.9% could have been just written/pasted into the JS file (which is ultimately what Figma runs).
To be honest, in the appropriate context I will contradict myself and say that that you should think of TypeScript as a separate language. There's a lot of dynamic things you can do in JavaScript that will interact poorly with attempts to statically reason about your code with TypeScript; even if it's the approach you'd take in JS, when you add typing you should recalibrate how you approach the problem - that, to me, is an argument for thinking of it as separate language.
...but that's mostly just what I say to JavaScript devs, to be polite - to not tell them that their JavaScript code is bad, too. Code that's difficult to reason about statically is strictly worse, in my opinion, than code that's easier to reason about statically. And in that sense, TypeScript is just guiding you to write better JavaScript, which maybe undercuts its claim to being a language of its own.
I don't want them to "learn JS." Most likely the person in question is trying to write web applications, and I want them to learn what is most useful for that. After writing web applications for years without TypeScript and then for years with it, I cannot imagine going back. I can make complex refactors with very little worry. Thanks to type inference, most of the TypeScript code I write is indistinguishable from JavaScript, so the idea that learning TS takes away from learning JS is ridiculous. When I suggested that the extra syntax might be distracting at first, I meant for like... a week.
I very much concur that it is better NOT to introduce TS when explaining JS fundamentals. I've seen smart engineers with a C++ background get tripped up on and very confused working with TS, because it's not clear to them what concepts are "language fundamentals" and what concepts are "the TS transpiler".
(Like expecting that just because you declared something as type X, that it guarantees at runtime it will always be type X, but it won't. You may get data from an API that _says_ it returns type X but the contents don't match. That can be valid code that compiles and has weird runtime behavior)
What helped me understand the Runtime behaviour of TS is to understand that TS doesn't actually have strong typing. If it was named "LintScript", its name would be much closer to the truth.
This statement is quite questionable starting from the fact that there is no definition for what strong typing is.
Care to provide what you mean?
Strict TS won't compile pretty much any type-unsafe operation.
It's not perfect, the standard libraries are a bit too unsafe type wise, exceptions are untyped and need Either/Result-like data types to be handled but it's an extremely powerful language if you know it and it's ecosystem.
Most people though don't even bother reading the docs and can't tell you what a mapped type is or what is a disjointed union, etc.
If you are in a completely self-defined world, then yes you can trust the compiler. But I once built a react component which was called from library code and it simply did not adhere to the method signature (this was for a material UI table extension).
As soon as you have third party code calling your methods all bets are off. It could be JS calling your methods, or there simply is a hidden cast somewhere.
This is the moment that you realize that type annotations really are just a compile-time fiction, much like Python. At least in my definition, this is weak typing as the variable is physically capable of changing to any type at runtime, despite its type annotations.
TBF, this can also be true in C++, C#, probably most languages that can interoperate with other systems not written 100% in the same language + same runtime. After a while, you just get used to not trusting anything at the boundary - types are for your convenience and your internal logic, nothing more.
You are talking about something entirely different. Having weird interop is one thing. But having your internal state compromised because the language does not perform runtime checks is something entirely different.
In case of C++ this would lead to desastrous memory corruption. If all data is dynamic you can't have a safe program as data on the stack must be monomorphic or you corrupt nearby memory.
Naturally, you can defend against hostile input via excessive defensive programming (asserting against nulls, asserting against wrong types etc.). Or you simply use a strong static typed language.
Do you mean runtime type checking? Coming from compiled type safe languages, it was difficult to wrap my head around full type erasure too. Your name would have definitely helped.
Agree. I wish tools like zod/valibot were first class in typescript.
Also effect schema if you're looking for something much more powerful and in effect-land.
This is exactly why I never recommend TypeScript to new developers.
A similar problem (that used to be worse) with people learning JavaScript is the lack of separation between JavaScript and the DOM + browser APIs. 10+ years ago, people have told me how much they hated JavaScript and when probed about it further, would admit that it’s actually the DOM or new/inconsistent browser APIs that have caused issued.
JS has a number of its own flaws and quirks, yes, but there are two fundamental issues that make it harder to approach as a new learner (as opposed to, to say, Python) are how tightly coupled it has historically been to it’s primarily application case and how high or low level is this language?
The idea that someone is good at another language so they'll automatically be good at another is a common misconception. In fact, they're likely to be worse because they're less likely to spend time trying to learn things from the ground up and less likely to write idiomatic code.
It's especially bad with js/ts because of it's popularity (so lots of new programmers that complain about how NaN doesn't equal itself), and because it's the defacto web language so lots of people are forced to use it as a secondary language that don't want to spend time learning it.
It is (or should be) common practice to parse/validate any external data you depend on. You should be doing this for Javascript too. I find that the library https://zod.dev/ is quite helpful for this
It's better if they learn the core language and then graduate to TypeScript (if at all, as there's active discussion of adding type annotations to the core language [1]).
An anecdote: I was sold a similar story on CoffeeScript back in the day, stressed myself out learning it, only to discard it a couple years later. TS won't have an identical fate as its shepherded by Microsoft, but eventually it will go the way of the dodo (whereas core JS will still be humming along).
[1] https://youtu.be/SdV9Xy0E4CM?feature=shared&t=380
This was the approach one of my first mentors recommended and it's served me well. Learn the core language and its features and then add tools/frameworks as needed. Lately it feels like we're teaching new devs popular frameworks and completely ignoring the fundamentals.
Yep. But business requirements dictate what happens and these frameworks are the fastest way to achieve business goals, which sucks as when the frameworks lose their appeal, those devs are gonna struggle to transfer their skills to something else.
It is useful to know vanilla JS. Right now I am learning an integration platform that uses JS for its scripting language, but you cannot use TS.