Ask HN: How do I learn JavaScript?
I feel like I would like to learn modern JavaScript (as supported by the most recent version of V8) from the very basic to the perfect and complete level (which makes the whole point of the question, ways to mediocre proficiency are countless and obvious).
I believe this is possible (and maybe not even hard) as I only mean the language itself - no browser APIs, no frameworks/libraries/tooling, no patterns and practices beyond those necessary to understand the features and the quirks of the language itself, what they can be used for and how to deal with them correctly.
Where do I go and how hard is this actually going to be?
127 comments
[ 4.3 ms ] story [ 319 ms ] thread> Where do I go?
You don't really need to go anywhere else (especially not into the vortex of looking for the best resource) to learn and be confident with vanilla javascript.
> ... and how hard is this actually going to be?
Well that depends more on you and your preference for learning materials. I studied a chapter a day (like 3 hours concentrated per day) and was done in 3 weeks.
I have bookmarked few other links from HN
https://news.ycombinator.com/item?id=13979472
https://github.com/getify/You-Dont-Know-JS
https://www.robinwieruch.de/javascript-fundamentals-react-re...
If you don’t know any programming, it’s a bad idea to start by JavaScript. Its design has followed a path from a hackish webpage scripting language to being used server-side, so a lot has evolved and a lot of crap remains from the old days. If you don’t know programming, you’ll have a hard time discerning the newer, cleaner features from the older less polished ones.
In my opinion it’s easier to learn java or C or Kotlin, which are a lot neater. And then learn about how JavaScript differs.
now that book is old and es6 changed a lot of things, so find a good book read it and if it has examples go thru them. only with examples was i able to understand scope inheritence and asynchronous calls in javascipt. like if you call settimeout in loop and all other gotchas.
It takes years to become good at programming. Once you know programming, it usually takes hours to learn a new (procedural) programming language.
Really? I feel like I’ve spent longer than that just trying to get my head around JavaScript’s prototypal inheritance. I’m even more confused by Promises.
You can think of a prototype as 'cloning' an object (but not quite), distinct from classes in OOP, which are typically created afresh, i.e. no entanglement occurs between instance 1 and 2 of the same class (unless of course explicitly specified in a constructor). If I have `var a = {one: 1, two: 2}`, I can use that as a 'live template' to stamp out other 'instances' that prototypically inherit from that ancestor. Any attribute lookups that are not specified directly on an object created with a prototype recursively look up the prototype ancestry chain until it is found. So if c -> b -> a (where a -> b means a prototypically inherits from b), looking up a property on c will try to look for the property on c first, failing that b, then a. If nothing is found, `undefined` is returned.
Let's open our inspector and have a play: ``` var a = {one: 1, two: 2}; var b = Object.create(a); // create b, based on prototype a var c = Object.create(b);
console.log(c.one) // 1, how, when this wasn't even defined! We looked up the p. chain until we found it
b.three = 3;
console.log(a.three) // undefined, a's only prototype is Object console.log(c.three) // 3, wow, c knew about something that happened to b! This is different from OOP. 'instances' share data defined at runtime.
```
Why promises? Before promises, js code often used an error first callback strategy to communicate when an asynchronous process has finished. It's important to write blocking code as little as possible, since your computer can and should spend time doing 'compute' stuff, whilst waiting for a resource, such as a network request or disk etc.. which can take an unbounded amount of time.
Back to how callbacks look: ``` function myExpensiveSuccessfulFn(cbFn) { setTimeout(() => { cbFn(null, 'success'); // pretend we did something useful }, 60 * 1000) // time waste for a minute }
function myExpensiveFailingFn(cbFn) { setTimeout(() => { cbFn('oh no'); // pretend we tried to do something useful }, 60 * 1000) // time waste for a minute }
function myCallback(err, data) { console.log(`err: ${err}`); console.log(`data: ${data}`); }
myExpensiveSuccessfulFn(myCallback); // after 1 minute: err: null, data: 'success'
myExpensiveFailingFn(myCallback); // after 1 minute: err: 'oh no', data: undefined ```
Awesome. We can wait for some result and be notified whenever it finishes. Have a play in your inspector as before. Immediately after calling our expensive functions, we can execute code straightaway (try logging anything immediately after calling an expensive function)
Now callbacks start to get unwieldy when those same callbacks also want to do things that require something else asynchronously. There are better examples online, but I'll write something with anonymous functions to give you an idea:
``` function addSomethingSoon(a, b, cbFn) { // in 5 seconds, return the sum of two numbers setTimeout(() => { cbFn(a + b)// no err first style in this example }, 5 * 1000); }
// now let's get the sum of four numbers:
addSomethingSoon(1, 2, (result1) => { addSomethingSoon(result1, 3, (result2) => { addSomethingSoon(result2, 4, (finalResult) => { console.log(`1+2+3+4=${finalResult}`); }); }); }); ```
Only 3 operations, and things are getting quite ugly. Contrived, but let's see how we can do better.
Enter the promise. A promise is a 'promise' of a future result. It's like if you went to a fast food restaurant, made an order and got a ticket in return. Once you are given a ticket, they'll call out your number and give you your food, since you are holding the ticket (the promise of food in the future).
Let's have a play:
``` function getFoodIn5(menuItem) { // don't worry about the syntax here. You'll likely not be creating promises with 'new' often. You'll likely get given them from a library, say a http call or similar. return new Promise((onComplete) => { setTimeout(() => { onComplete(`fresh ${menuItem}`); }, 5 * 1000) }); }
const promiseOfFood = getFoodIn5('burger'); console.log(promiseOfFood) // depends on your browser, nothing very useful, and definitely NOT our burger....
promiseOfFood.then((food) => { console.log(food); // fresh burger, yes, it tastes so good! }); ```
So we got our burger, pretty fast too. Unfortunately they just hired a few trainees:
``` function burntFoodIn5(menuItem) { // don't worry about the syntax here. You'll likely not be creating promises with 'new' often. You'll likely get given them from a library, say a http call or similar. return new Promise((onComplete, onError) => { setTimeout(() => { onError(`burnt ${menuItem}`); }, 5 * 1000) }); }
const promiseOfFood = burntFoodIn5('burger'); console.log(promiseOfFood);
promiseOfFood.then((food) => { console.log(food); // ... :( nothing }).catch((mistake) => { console.log(mistake) // burnt burger, you don't want to eat this. }); ```
that is promises in a nutshell...
That said, if you want a comprehensive read about Javascript, there's You don't know JS: https://github.com/getify/You-Dont-Know-JS
https://www.youtube.com/watch?v=qoSksQ4s_hg&list=PL4cUxeGkcC...
https://www.youtube.com/watch?v=iWOYAxlnaww&list=PL4cUxeGkcC...
I'd also use various materials, like books or courses online.
Finally, start a small project in JS, best way to apply your knowledge and discover gaps.
However, just being able to do something in a language and being able to do it the most correct and future-proof way is different, and in JS, "best practices" seem to be constantly evolving with language and community. Every library and framework seem to be doing things in a slightly different way, and there's a lot of freedom to experiment with different coding styles and programming paradigms (unlike in a language like Go). Personally, I would suggest Typescript for professional projects, but there are plenty of very knowledgegble and competent people with a lot of different opinions on it. If you're the kind of person who likes this kind of environment, you'll fall in love with JS ecosystem.
I just went to the console and tried all things that should and should not have work. There you’ll learn about the specifics of prototyping, properties, operators, everything, and get insights for what’s going on under the hood. Didn’t find these details anywhere else. All sources of information are situational, down-to-earth utilitarian and resemble grandma’s cooking recipes, while what you seem to want is precise chemistry. (ed: another problem with js is that most books on it are out of date by design, e.g. one of the suggested links around says that prototypes can only hold methods and not values; what else is wrong there?)
>no browser APIs
A big part of js internals lies in the Object namespace. See also Symbol. (MDN for both)
It doesn't cover the complete language, in particular it doesn't cover all outdated concepts and backward-compatible features. To get a complete understanding you would have to read the JavaScript specifications, but I don't think it makes sense to start there without having a solid understanding of the basic concepts first.
If you want to dive deeper, you can then read Deep JavaScript[1] by the same author.
[1] https://exploringjs.com/deep-js/index.html
How does one take this knowledge and learn the browser APIs (in particular, best practices around those APIs) plus to navigate the frontend ecosystem in general without getting overwhelmed? Obviously you learn the APIs by building stuff, which I do. I can and do write frontend code, but always with the feeling that I've never learned this stuff properly.
I know there are tutorials aplenty on this stuff -- other than MDN, is there anything authoritative, comprehensive, and deep? Like, the SICP or TAOP of frontend programming?
I would recommend the official spec. It won't be an easy read, unless you're already used to reading standardese, but there's nothing more authoritative than that.
[0] - https://github.com/getify/You-Dont-Know-JS
[1] - https://www.ecma-international.org/publications/standards/Ec...
I don’t think you can master a language in one go. It’s not how most people’s brains work. I think you do it in stages. Get yourself a good introductory JS resource. The eloquent javascript book others posted looks good although I haven’t read it myself. Then read You Don’t Know JS. And then study the spec. Almost by definition the spec is the only thing that can give you a perfect and complete understanding the language. But don’t start there as a complete beginner is not its intended audience.
Be sure to apply what you learn from each book by working on projects. Don’t just read the books. The material won’t stick that way.
If Fabrice Bellard can do it, in C, with no dependencies, you can do it in whatever language you're already comfortable with, using the standard library. It's simply a matter of sustained effort and focus over time.
But looking into the details of how object prototypes and properties really work is essential for getting a good grasp of the language.
At some point, that knowledge can then be applied by learning more advanced language features such as implementing Proxies, Generators, and template literal functions.
To do so, some here are suggesting you read the language spec. I think Rau schmaer's series "Exploring ES6" [0] (and then ES7/8/9) is a great alternative to the actual spec. In those books he basically goes through the new features of each version of the language and does the deepest dive I've seen, with examples and references to the spec.
[0] - https://exploringjs.com/es6.html
I do believe you need to have worked in JS for a while before jumping into YDKJS though. Having hit some of the idiosyncrasies of the language in the real world makes the book a much richer learning experience.
The author, Kyle Simpson, has some really good video courses available online as well. He goes further in depth about some of the more interesting topics in YDKJS and is really able to sell some of his patterns.
Again, Kyle’s material was better digested after some practical experience with the language.
JS is a rather forgiving language (maybe too forgiving) that's very suitable for learning by trial and error. Get the basics, start hacking, find what works and what doesn't, look at other people's code to draw inspiration etc...
I've worked with JavaScript many times through the years, and never felt that I got close to becoming an expert no matter what. The language it self is in the way. Browser compatibility, language weirdness (like the =, == or === mess) and there are a lot of standards around. But now a days working with ClojureScript, which settles the language problems, I get to focus on getting good at libraries, react and browser-stuff.
I hope I never have to work with vanilla JavaScript again, but since ClojureScript is a niche I'm pretty sure this dream will burst at some point. But I can attest ClojureScript has brought significantly more enjoyment into my life when dealing with front-end development.
Unfortunately your chances of getting a job doing ClojureScript is probably slim to none :(
Sneak ClojureScript in. I know of one shop that trained its JavaScript engineers to use ClojureScript in two weeks. Quite frankly, if one is smart enough to write actual good, safe JavaScript, then one can definitely grok ClojureScript.
We have an old creaky app which I'm tempted to rewrite in ClojureScript in my own time and then show them it.
Worst case scenario they say it's great, now can we please rewrite it in JS. Best case scenario I get something in Clojure / CLJS into our system.
Either way I'd probably learn a lot just from the project. And I kinda need a new side project at the minute.
Linux did not win the server space because admins snuck it in. It won because it was free and worked well enough compared to signing up for tens of thousands of dollars worth of lengthy contracts with SCO/HP/IBM or even Microsoft.
> Sneak ClojureScript in
I don't see this ending well.
It's great to do your side projects in your favorite language but foisting it onto your employer so they they are forced to use it is a pretty bad violation of trust.
What happens if you quit and ClojureScript programmers are hard to find at the price the employer can afford without going out of business?
I would never try and pull this off.
Many companies would not or because of SLAs _could not_ use free Linux. They would pay RedHat or Suse fees that included support/maintenance. Yes, it was still usually cheaper than Window licenses, but the price was not really the point.
Now about sneaking languages, platforms, and stacks in... Java was once too risky and unknown to be used in place of C/C++, but we snuck that in and proved it was up to task. Python... hah, Python was a toy "scripting language". No self-respecting CIO would approve of building company products in Python. Ruby? Rails? Surely not, those were also free, unknown, unproven technologies (which ironically were trying to supplant Java-based systems... that same Java which was once too risky).
PosgreSQL or MySQL? No way, that's not reliable for production. Of course it is, and it got snuck into companies whose engineers despised Oracle and SQL Server (not because MSSQL sucked, but because it only ran on Windows).
You can pick any modern best of breed tool, and I can point in history when that tool had to be snuck in to prove itself and gain acceptance.
I don't like the idea of "snuck in".
Working with management and having buy in that there's going to be a risk involved in taking something up that's new and unknown is OK.
That way we have a plan and action in place if things go other than expected.
That is exactly why I left a BIG5 firm and now work at startups because I can run these by the CEO and have a discussion.
The place where I work does not exist for my amusement.
Many people's livelihood including those of close friends and their families depend on the decisions I make.
If I am at a VC funded startup I am playing with the retirement of millions of people.
I owe it to them to be in the know of any risky decisions I take that I judge to be risky enough to affect them negatively.
Anything that's new and relatively unknown is risky.
That does not mean we don't try it.
It does mean we need to have a plan and action in place if things go other than expected.
Thats just good engineering and business because people depend on me.
Otherwise it's just a hobby and pastime.
My email is my handle at gmail.com
No obligation. I just want to connect with an individual interested in a "non-traditional" language :)
So as a Java developer ClojureScript keeps me a little in a familiar realm instead of jumping to a whole new ecosystem where I have to pick up every new aspect in the tool chain, including the language.
But this is personal, and I have absolutely no experience in these other languages you mention and they may be awesome.
+ Use Typescript (no, it's not the same as JS)
+ Use ClojureScript
+ Use Elm
+ Use Reason
+ Use ...
If you go back about five years, you'll find this pattern also exists, except all the things people were saying to use are dead. Dead like a forgotten Egyptian pharaoh - buried and never to be seen again.
Unfortunately, all the code bases written in these poor JS-likes are still alive and I and many other poor souls still have to maintain the dang things.
You know what's still alive? Javascript. You know what still basically works the same? Javascript. You know what codebases from five or seven years ago I don't mind maintaining as much? Javascript.
ClojureScript and Reason are superior languages, period. They will live long happy lives, too.
I suspect that most of the ones I name will join the bone pile of the many other "superior languages" or continue to be used at most by a niche few.
There is no relief in sight and it'll suck for a long time because everything is very fluid everywhere. Legacy will suck.
But if you want to be as productive and confident as you can these days; my take it is to not engange in vanilla JavaScript.
https://javascript.info/
Pure JS will be a bit boring. You’d want to learn some Node apis to do something useful. But you could limit it to file I/o if it’s the JS you want to focus on. At least that’ll give you some async experience which I’m sure you’d be keen to learn.
This course really pushed my js knowledge forward!
https://www.udemy.com/course/understand-javascript/
After watching that I would recommend https://github.com/getify/You-Dont-Know-JS and that should give one a solid base.
[0] https://bellard.org/quickjs/
"If you think you understand quantum mechanics, you don't understand quantum mechanics." - the same is true for C++ which is one of a few languages impossible to learn to the perfect and complete level.
I don't mean babel. I mean from scratch. Using whatever language you're comfortable with, turn lists of expressions into JS code.
https://github.com/sctb/lumen does this in just a couple thousand lines.