A Modern JavaScript Tutorial
javascript.info
javascript.info
I might be sounding like a promoter for it, but it really added a lot of value for me personally, so just wanted to spread the good word.
https://news.ycombinator.com/from?site=javascript.info
I sometimes wonder what are the dynamics that trigger the snowball on HN.
By novelty I mean something that is easily recognized as new and important. It doesn’t help that something is new if no one catches the point of reading about it. Could be a bad title or a bad article. Or bad luck.
In terms of good luck I mean a couple of specific things especially:
- If a few people see it that are excited about it, either from hearing about it the first time or from knowing it in the past, and these people write positive comments about it, then others who come across the post may be encouraged to check it out and to upvote it too.
- “Micro zeitgeist”. If it’s about a topic that recently hit the front page and it adds something new about that, it could luck out. Why luck in this case? Because you probably don’t know ahead of submitting that people will care to read even more about some topic even if it was popular the day before. Perhaps instead people are tired of the topic.
- The other things submitted the same day did not gain enough traction to push this thing away.
- Evergreen topics that have not gotten traction in a while but that people care about.
- Topics that people in university and college are currently learning about so it catches their attention. I dunno how big the amount of people currently in university is versus people that are in jobs. But I remember that I learned about HN from some other students in a student union I was in back then. And I don’t know how students HN reading habits are compared to people in jobs either. I remember reading HN a lot when at the university. But I still read HN a lot. These days I read HN in the morning, the evening and at night though, not when I am working. But even if you have a job you might read HN in the lunch break, or perhaps you have some downtime where you are waiting for something at work and you read HN for a while.
There are other possible factors too that I have thought about in the past but these are the ones I can think of right now.
Please note that all of what I am saying here is only my thoughts based on my own habits and from what I’ve heard other people say and what I’ve seen.
Whether conscious or not (probably mostly conscious) I think they simply had the same temporal relevance for other people as they did for me.
All that said, I don't know what it would be in this case. I expect I'll find it useful though, being not really a JS person who does need to write some JS and would rather maintain decent JS than awful.
What it seems to lack, which I find a sticking point whenever I consider some greenfield personal project, is the dizzying array of 'tooling stuff' that JS has, and how it does or doesn't fit together, etc. There's just all sorts of weird layers and not quite equivalents and can be equivalents but could also be used togethers, half the stuff it's not even clear what it is or if it's necessary at all.
I really hope wasm brings more different options (hard to phrase that to not sound hypocritical!) one day; that we just have some tiny JS shim that everyone uses, and other than that it's totally arbitrary which language and ecosystem you use, JS an option, but no more obvious than anything else.
Aha, yes, this. I am [currently] a JavaScript person and it is a shitshow. The cliché used to point and laugh at JS is framework churn, but that's not really much of a thing [imo], it's the tooling. The tools can be genuinely very good if you pick the right combination in the right context, but that's often more luck than judgement.
I suspect as wasm usage becomes more widespread, it'll get worse, not better, at least for a while. There's always a shining future to hope for (and despite the gripes, things have generally improved steadily over the years, so not too idealistic a hope).
If Rome[1] fulfils its goals (big if), then you might get what you want. Very early days though, and going to be very hard for the maintainers to keep control as the scope of the project expands.
Aside, but I think it would be interesting to figure out how much cargo culting is going on with JS tooling. Theory: most configurations of tooling beyond "install CRA/similar" are built up via Googling done when building out highly context-specific configs -> that brings back articles on how to set up tooling that was specific to the author's particular situation -> they are used in lieu of the tool's documentation because Things Just Need To Get Done Now and it's just some dev dependencies, whatever -> those configs are used in a situation they aren't needed -> process repeats.
It starts off by giving installation instructions for yarn/npm/npx. Which should I use if I'm starting a project and I heard on HN Rome is the easy one true way to do it? I don't already have yarn or npm or npx so there's no existing reason to care, but now I feel I need to find out about them and their potential tradeoffs since it's probably easier to choose now than change later.
And then you get past that and want to use LSP with your editor, and realise it's not one tool to rule them all after all anyway!
I realise you may be being slightly facetious to make a [fair] point, but if not: Yarn and NPM are package managers, NPM comes with Node. npx is a command line tool for npm that generally obseletes most need for globally installing packages, it is a small but nice nice recent improvement to the JS ecosystem.
LSP is a protocol implemented by plugins for text editors/IDEs, it's got nothing to do with a specific language, what do you mean by mentioning that?
LSP has two parts, a client implented by an editor (or plugin for one), and a server for whichever specific language.
If you always use vim but several languages, you need one language client for vim, and a language server for, yes, each specific language you want to write with it. `vls` for example for vue/js/etc. distributed with `vetur` which is God knows what also distributing God knows what else, and the rabbit hole continues. :)
(And your language server might be the only linter and formatter you need/want, so they're then wasted being in Rome, is what made me think of it.)
So Yarn was created to deal with issues in NPM (amongst other things: speed, problems with package duplication, no lockfile). AFAICS from watching Ryan Dahl talking about the process of his developing Node, NPM was kind of an afterthought, so it has some flaws that are difficult to fix because they're so ingrained into how Node works.
So Yarn [v1] has a very similar API, and uses the NPM registry, and works in a very similar way (dependencies go in node_modules, etc etc). Most of the time, when you see the choice, the author of the documentation is talking about NPM vs. Yarn v1.
Competition from Yarn [v1] was a generally good thing despite the slight confusion it causes, because what it did was force NPM to update to include some of Yarn's better features, in an attempt to gain feature parity.
The existence of Yarn v2 is also now [imo] important because of its two main features that differentiate it from NPM. Its API is basically the same as NPM, but the way it works is not, and yes, it's confusing. It works (and works very well), but I think its core value (and the reason why IMO it should be pushed alongside NPM despite the confusion that is likely to cause) is that it's acting as a testbed for features that are probably useful to the JS ecosystem. And the wider the usage, the more those features can be battle tested:
- it has full support for monorepos (storing all code for all associated projects in a single repo) which can make development easier in what would seem to be a large set of contexts.
- it allows a user to dispense with node_modules through a mechanism called plug and play. Dependency management is much better than NPM, issues with dependencies are easier to locate, and unless there are new deps added, there is no install step after the initial one (I can push my code to a repo, someone can clone the repo and just start the application immediately). This IME has fairly significant DX benefits, as well as making CI tasks take significantly less time and resource.
[1]: https://documentation.divio.com/tutorials/
[2]: https://documentation.divio.com/how-to-guides/
Edit: I don't mention this to be nitpicky. I mention it because I wish that we would collectively start standardizing those terms. I think it would be helpful if, whenever we saw "… guide" or "… tutorial" we had a general idea about the structure and purpose of the contents. The Divio links above do a great job at explaining each doc type. I'm simply sharing this idea for people who have never considered being more careful about how they label their docs and would like to start following general technical writing community practices. As a practicing technical writer I can tell you that the TW community mostly agrees upon what each doc type entails ("tutorials" and "references" have strong consensus; "guides" less so).
1. Tutorials "are lessons that take the reader by the hand through a series of steps." They "are oriented towards learning how."
2. How-to guides "take the reader through steps."
3. "How-to guides are wholly distinct from tutorials."
If I found a "community" around a topic, do I then get to decide what words mean? By consensus, of course.
https://documentation.divio.com/introduction/#the-secret
It's certainly a valuable take, even if you disagree with the claim that all 4 functions are required for good documentation.
> oriented to: learning
> must: allow the newcomer to get started
> its form: a lesson
> analogy: teaching a small child how to cook
It does not satify all the requirements of any other column.
> How-to guides take the reader through the steps required to solve a real-world problem.
That is from the linked article on how-to guide. By "real-world problem" it means something specific you might want to do to a real code base, like "switch to a different database engine" or "add user authenticaion". That's why it includes the qualification "real-world". The original article definitely does not fall into that category.
> * A tutorial is what you decide a beginner needs to know.
> * A how-to guide is an answer to a question that only a user with some experience could even formulate.
That was some extra clarification from the linked article on the difference between tutorial and how-to guide. That makes it even more clear that the article is more like a tutorial than a how-to guide.
> Tutorials are lessons that take the reader by the hand through a series of steps to complete a project of some kind.
That's from the page about tutorials. The article introduces a reader to a substantial new topic from scratch and guides them through it, but it doesn't do so by making them complete a specific project, so it doesn't fit this definition.
But that doesn't stop it from being a "tutorial". The requirement that tutorials have to involve completing a sample project is invented by the author of that page and not part of the usual definition of that word.
This final point is pure conjecture, but I suspect the author of that page was just trying to strongly encourage people to base tutorials around sample projects. It's fair to encourage that, because often tutorials are improved by basing them around a single unifying project (but not always). But putting it in their definition of the word was a mistake, because that's not what that word means, and it's only created confusion.
There was a big push for that a while back. The JavaScript community can be silly.
Here’s an example great bike shed discussion from ~10y ago about whether or not to use semicolons with JavaScript.
“If you don’t understand how statements in JavaScript are terminated, then you just don’t know JavaScript very well, and shouldn’t write JavaScript programs professionally without supervision, and you definitely should not tell anyone else how to write their JavaScript programs.”
Those were the fun days! :)
Just about anyone who's ever written JS probably knows about the heavy lean towards "always use `===`". And it's not without good reason, because there are more than handful of not-entirely-intuitive implicit coercions/comparison corners associated with `==`. Personally, I think it's OK to use it, but I understand that it requires knowing the rules associated with use and most of all comes with the overhead of keeping them in mind when you do so. Most of the time it will be OK if you know even most of the rules. Sometimes it will not be OK. More often the overhead will cost you attention to other things. Some people have made the call "wouldn't it be simpler if we just did strict comparison and saved our attention for other things?" and while it's not my first choice, I can understand and respect it.
The statement termination thing strikes me as pretty much the same. Sure, if you know the rules, you can do it freely. But it takes something explicit that you don't have to think about and turns it into something implicit that you do. It isn't going to be a problem most of the time, but sometimes it will not be OK. A little more often the overhead will cost you attention to other things. Following the rule that semicolons terminate statements hasn't ever cost me anything.
The weird thing in my experience was the frequent overlap between antisemicolonists and always===ists. My theory is that mostly these people came from Ruby and Python, liked less punctuation for subjective aesthetic reasons, and didn't actually know the coercion rules well or particularly like JS, but that's speculation.
If for any reason you absolutelly can't have these in place, better be safe and use semicolons.
Edit: for the "gotcha" explained in the link, prettier will automatically insert a semicolon before the array.
keyword "yet". It seems like such a insignificant win, with the downside being some very hard to debug runtime error because one element of your build chain has a bug or misses an edge case.
I honestly don't see the logic.
And here is the upside: I've minimized the time I spend arguing about this detail with my colleagues to 0s. Because it doesn't matter :)
We have tooling that can solve this to prevent pointless bike shedding.
It's nice to not waste a single braincycle on these things anymore.
ie languages aren't nearly quite so important as the platform.
Stuff wasn't written in js because early js was a brilliant language - it was because the platform - the web - was brilliant.
Many have written 'better' languages that compile to js - https://github.com/jashkenas/coffeescript/wiki/List-of-langu...
and while typescript is one of the better, more supported ones, isn't it just another one?
Surely in the end it just adds complexity and fragmentation of the ecosystem?
TS really is different from other compile-to-js languages in this respect.
There is JS code I deal with once a month where the manipulation of types is so complex I probably burn ~30 minutes every time I have to touch it. If that was was transformed into TS (which is going to happen eventually) that'd be 30 minutes saved per month, on this one particular flow of data.
I've done refactorings that were only possible because TS existed.
A lot of JS unit tests consist of "ensure these fields exist on this object after it has been called by these functions."
Typescript removes the need for those tests.
And it removes the need to update those tests every time the code changes (just change the declarations appropriately!). And it removes the need to run those tests on every commit.
That said, the overall code/compile/run time savings is possibly not in TS's favor due to how slow the compiler is. :/
Typescript compiler supports (some) JS DOC
https://www.typescriptlang.org/docs/handbook/jsdoc-supported...
So you can use the compiler as a static analysis tool without buying into the language itself completely, which I do and just stick type definitions to comments when needed.
Though the attempts at close compatibility mean it's not properly type safe despite it's name.
In the end, it's still a 'splitter' to quote Monty Python.
Every type checked language I've used, from Haskell to Java to Idris to C++ to Rust has ways to override the type checker (and either do the type checking at runtime, or, as C++ is often want to do, just YOLO it). It's not just the language but the codebase and the norms it and its dependencies use.
Some TypeScript codebases, the types are usually accurate, but not enough to rely on them, so you still need to do runtime checks in many places. In others, if something says (string|null) then you know with confidence that it is either a string or the null value, nothing more and nothing less.
Lol. I switched to TS from pure JS a couple years ago and could never imagine going back. I am so much more productive in TS than JS:
1. Typeahead is crucial, and even when just working on my own projects it makes me much faster.
2. Refactoring is a scary nightmare in pure JS, but so much easier with TS.
3. I have yet to see any sizable, multi-person pure JS project not become an incomprehensible nightmare after a couple years. TS makes large codebases much easier to maintain.
There are other reasons.
If anything, the consolidation onto TS from previous competing type systems for JS (e.g. I think Flow is dead for all intents and purposes, and I've seen a number of projects migrate onto TS from Flow) results in less fragmentation.
Are you doing server stuff with it?
You could argue here there are much better languages and platforms for that.
I still don't get how we got from fifty lines of code for a form with simple client side validation to a React/Vue/Angular/Next version that needs 100 different modules and a thousand lines of code to replicate. Why do people see this as a huge advancement in front-end development?
Modest SPAs do have a lot of code. So does a C++ Win32 application that calls into some central datastore. The complexity is not a byproduct of languages or libraries, but rather the customer's complicated needs.
i'm working on a webapp with a scheduling thing and even drawing a nice-but-not-interactive day schedule is a bunch of work. consider a day view that lays out overlapping events next to each other:
Dec 8
-----------
9
10 AAA
11 AAA BBB
12 AAA BBB
13 BBB
14 CCC BBB
15 CCC
16
17 DDDDDDD
18 DDDDDDD
19
like, even laying out those boxes takes a bunch of code. and then you need interactivity, the actual "app" part - you want drag-n-drop that snaps to columns and switches you to another day if you drag it to the side, and selections, and menus, and hovery-popupy things, and undo, and so on... it adds up quickly> You could argue here there are much better languages and platforms for that.
You could, but I think you'd be wrong. I come from a background of using Java on the backend for over a decade, then some time with various backend languages including Python and Ruby. This is the first time in my career when everything (front end and back end) are essentially on the same stack, and there are huge, gigantic productivity improvements to that. Most of it stems from it being easy for developers to switch between front end and back end code. E.g. it's very easy for front end developers to dig in and debug something that's not right on the back end, and usually to fix it themselves. Same thing goes for backend devs investigating how APIs are used by the front end. In all my previous jobs it was relatively rare (certainly not never but not that common) for devs to cross that divide, mainly because setting up the environment in a totally different stack was time consuming and annoying, and mentally context switching into a different language was difficult, if all you wanted to do was dig in on one particular endpoint, for example.
But even discounting that, I am much more productive in TS than I ever was with Java, primarily because the structural typing of TS makes thing much easier to refactor compared to the nominal typing of Java. Sure, there are some cases (mainly WRT scalability) where Java may be a better choice, but the idea that TS/Node is not an awesome choice for the server is outdated IMO.
That's interesting. This year I switched from server-side Java to server-side TS and I find that refactoring is incredibly painful when compared to Java. I think any productivity gains in the greenfield portion of a TS project are quickly offset by the pain of refactoring and debugging during maintenance. It's really disappointing, as I quite like TS.
The "blast radius" if you will with nominal type systems is just always much larger.
You edit a file and reload, no munging pipeline,
Most websites are what I'd call "broad and shallow". For any individual action the corresponding code path is small. Most code in these sites is easy to write and easy to debug in vanilla JS. Typescript adds boilerplate and compiler times for type safety the development team was doing fine without.
However there are some sites, usually very complex SPAs, that are necessarily "deep". Even small user actions absolutely must cause >10k lines of code to run. Type systems are often very valuable for the development of such sites.
It's my experience that some developers who've only ever worked on "broad and shallow" sites fail to appreciate what a time saver a type system can be for the right "deep" website.
Hence the statement modern web = ts is wrong.
Personally I used the zoom native client and not the web one.
I spend most of my time in offline office and not the web version
You might want to reconsider that; they have a pretty bad security track record: https://www.securemac.com/news/zoom-security-flaw-puts-you-a... https://talosintelligence.com/vulnerability_reports/TALOS-20... https://talosintelligence.com/vulnerability_reports/TALOS-20... https://blog.0patch.com/2020/07/remote-code-execution-vulner...
That's like saying don't use the web version cos your out of date browser can be exploited.
I create scientific models and simulations for use in schools. Whether it's simulating a hurricane, or continental drift, electronics, or molecular interactions, the simulations themselves need to run on the browser, and all the UI that provides the users with all the affordances to interact with the model needs to also be written in JS/TS.
I think your questions are just revealing a failure of imagination/experience for what kinds of applications run on the web these days.
I can see if you want to write an Excel in the web - that you might have a complex code base - but surely that's the exception - not the rule?
So back to the statement of 'modern web = ts'
Isn't that wrong - these applications aren't really web - and are the exception, not the norm?
This statement is meaningless to me. What makes it "no longer the web?"
"The web" now includes fully-fledged applications. It's fine to make a distinction between things that are full applications and things that are close to blogs, if you like, but it doesn't change the fact that many people develop full applications for the web.
And I think this is clearly a lot more common you are recognizing.
For several years I've been writing a large computer algebra system(CAS) that runs on a webpage. Every time the user puts some input into a text box the CAS runs. Depending on the input it may run as many as ~40k lines of code. There are no coherent lines upon which to split the CAS as far as anyone developing it can tell.
The CAS must run on the browser both to deliver on real time performance requirements and to keep server costs manageable (certain inputs will get even high end CPUs humming).
If breaking this SPA up is possible, it's not apparent even to engineers with >10 years of experience developing highly complex applications.
Other similarly complex applications run on the web, even if it's unusual.
But what could probably help keep your sanity for a CAS is to add a test case for every change to make sure the same input produce the same output in the future. As well as performance tests to avoid performance regressions.
The resistance in the JS community isn’t to “yet another language”, it’s to the perceived complexity of TS strictness/appeasing the compiler. I’m saying this not based on polling so obviously take it with a grain of salt, but I routinely search Twitter, GitHub and rando blogs for TS content and that sentiment represents nearly 100% of the anti-TS content I encounter.
And largely I find that in React-focused communities. Which having spent the last several years using TS on Node in production, and the last couple months working on a web project in React, it’s not remotely surprising. React and many libraries built on it have ridiculously complex types. That’s not because of TS but interacting with and satisfying those types at compile time is extremely frustrating even to me as a seasoned TS dev who has built libraries that take advantage of many advanced features in the type system (I just don’t expose that complexity to the API consumer).
Before Typescript most compile-to-js languages existed in their own world. You might have not liked them. But you'd never have to deal with them.
Typescript has become so popular that many top javascript libraries use it too. Whatever you think of it, sooner or later you'll be working with Typescript code.
(I'm joking)
My issues are not with strongly typed languages, they're specifically with TS.
I still don't know how it's possible to safely, cleanly make a library that other projects can consume comfortably with just TypeScript.
However, for JS programmers, worrying about types is habitual. Offloading that task to a robot is great, but it doesn't mean the habit will just disappear. Thus to them, TS seems to mainly add overhead.
Couldn't the same be said for COBOL programmes and GOTOs?
Even if TS's type annotations would be added to the language (like it practically almost has been, through Babel supporting it), you'd still want to run a tool as you write it to actually check that those annotations are adhered to, rather than having your code crash on the user when they are not. TypeScript is that tool.
I feel like JavaScript adopting type annotations in a similar manner will make TypeScript look the same as Mypy in many regards: nice to have, but not necessary most of the time because the parent language ships with most of its features.
Largely absorbed by modern javascript? ;-)
All parts together is $18 (epub + pdf). I am not a front-end developer so not much use for me personally but spreading the good word :)
I'm curious. How are my language preferences exposed through HTTP headers?
I think this was a charming way to request volunteers for translation, but I was a bit taken aback.
Edit: check out chrome://translate-internals/ if you are interested
The Loops section gives a very brief description of what loops are. This doesn't introduce anything of value to an experienced programmer, and it's nowhere near enough of an explanation for teaching imperative programming to a beginner.
Personally I'd suggest targeting experienced programmers. I only learnt JavaScript relatively recently, and I found it very frustrating that every JavaScript tutorial I could find was aimed at beginners (and that isn't an exaggeration).
For as good as the TOC and layout is, there's always something I miss when I read books from a website. I miss the spatial context: how much material I already covered? How much is left?
I like the linearity of regular books (that includes PDFs). If the book is a website the next best thing for me is when the whole thing is just a single page. Worst thing are epubs :-p (hate the way the layout works with those and how slow epub readers tend to be).
ps. I saw I can buy a PDF of this site, but just commenting in general.
As someone who doesn't use Javascript much... is there a way to force it to copy the current state of the original variable to the new variable, without it being a reference and without having to use something like lodash?
One way to have a deep copy which shares nothing is const copy = JSON.parse(JSON.stringify(object)); but that may not always work. In short, copying a arbitrarily large object will probably waste memory, so it should be a little hard so you don't do it unless it's really necessary.
> The ideal name for a variable is data. Use it everywhere you can.
There is one small comment at the top of the chapter, which says ‘Irony detected’. Is there really a whole chapter written Ironically? It would be very easy to read this and think it was real advice.
(And if it is real advice, and I’m completely misunderstanding, then I can’t possibly recommend this book).
The whole chapter is littered with clearly tongue in cheek remarks.
However, after reading that chapter, I really can't help thinking that you simply weren't paying any attention.
It's not just written in sarcastic tone (something that yes, could be easy to miss for many), but it's also littered with active dissuasion and explicit explanations of the pitfalls of using this style.
Examples:
> If you write like that, a developer who comes across this line and tries to understand what is the value of i is going to have a merry time. Then come to you, seeking for an answer.
> A quick read of such code becomes impossible. And when there’s a typo… Ummm… We’re stuck for long
> A fellow programmer who wants to work with elem in the second half of the function will be surprised… Only during the debugging, after examining the code they will find out that they’re working with a clone!
> First, the code becomes longer and less readable, and the second, a fellow developer may spend a long time trying to figure out what the underscores mean.
You can argue that the chapter is inappropriate, but I don't think you can reasonably argue that it's misleading.
"A JavaScript Ninja writes code that is brilliantly mysterious. When people read such code it should induce confusion and if at all possible, fear. Clarity is for the feeble. Obviousness is overrated. Obfuscation and secrecy: that is the way of the Ninja. So, how do you become a Ninja?"
How someone interprets a tongue-in-cheek chapter could be a good litmus test of their reading comprehension, grasp on the fundamentals, and (last, but not the least) basic sense of humour. I’d hate to see it removed.
If someone takes this section literally, I would be immensely curious how they reconciled in their mind that advice with what they (supposedly) read in preceding sections.
I'm not sure now which sections are and aren't.
It might just be my sense of humour (I'm the sort of person that doesn't need an '/s' tag and feels that it shouldn't be necessary if you told the joke properly), but it was pretty obvious to me even without the irony warning that the page was intended as a joke.
It looks like it was heavily inspired by the classic 'Tao of Programming' [0]. It uses a very similar style and even quotes the actual Tao Te Ching.
Oh and a second thought on /s. For some time I only got my news through satire sites like the onion. And after I switched back to "real news" sites, I could not believe it was not satire. I mean come on, the world and the internet was always full of dumb people, but when even very high ranking people and institution say really out of the world things in all seriousness - I came to the conclusion, marking irony as irony is sadly sometimes important, in those interesting times we live ...
But this new level is a bit unsettling.
Golang's landscape is full of one letter variables and abbreviations and it's not great.
Stuff that isn't easily understood should be named appropriately but shortness is encouraged.
If you're storing an index in a global variable or a struct field then it should be called "index" not "i".
Method receivers are usually always kept short because they're pretty self explanatory and the first thing you look at in a function.
I did browse the go code randomly and for example t, s, and b are terrible variable names in my opinion in this example : https://github.com/golang/go/blob/3ce865d7a0b88714cc433454ae...
You can find a lot of code like this.
But even if these names were not available, I don't think using `tpl` or `t` or `b` is what should be preferred.
All three are “the template”. So, they use polish-ish notation: the template as []byte, template as string, and template as *template.Template.
I use Go a lot, so I’m used to it’s conventions. b for bytes is obvious to me because I know ReadFile returns bytes (not a file handle or a buffer), but I can see why if you lack context, it can look odd. OTOH, I don’t use Rust, so when I read snippets with 'a lifetimes, they always look “wrong” to me.
fooBarBazThings.each(t => t.DoThing())
for (int i = 0; i < len(things); i++) { // i used here }
Some local code patterns are seen so often you understand it in one go. Something like fooBarBazThings.each(fooBarBazThing => fooBarBazThing.DoThing())
for (int thingIndex = 0; thingIndex < lengthOfThings; thingIndex += 1) { // thingIndex used here }
Just clutters things up. fooBarBazThings.each(thing => thing.DoThing())
It's more useful when the receiver of the method doesn't tell you as much, eg: getRecentPurchases().values().forEach(price -> priceStats.accept(price));//alert('DEBUG: SomeFunction: condition is TRUE');
Then, depending on what browser I'm debugging in, the post-processor changes that to either console.log, document.title=, or alert(
:)
Intro section has no context, especially how this relates to Crockford's "the good parts".
Is it inspired by it, in conflict with it, a superset, a subset? How did newer standards affect it? how is 'modern' defined? How is 'now' defined?
https://javascript.info/ninja-code
>Show your original thinking! Let the call of checkPermission return not true/false, but a complex object with the results of the check.
>Those developers who try to write if (checkPermission(..)), will wonder why it doesn’t work. Tell them: “Read the docs!”. And give this article.
I think if you've gotten as far as that chapter, it would be pretty impossible not to realize it was tongue in cheek.
At the top of the page is a big warning triangle that says "Irony detected."
No other chapter includes such a prominent warning. I think it's pretty clear that the "gag" is specific to that chapter.
The proper way is callback convention err. Then you can write if(!err) ...
In older scripts, you may also find another keyword: var instead of let
When I teach Javascript to students, javascript.info is one of the main sources I use besides MDN.
PS My copy of JS the good parts is getting a bit dusty somewhere in the garage...
Some things missing: Typed arrays, template literals, Internationalization API (Intl).
Date will be replaced with TC39 Temporal soon.
How could you explain me, strictly from the language design point, not practicality/how widespread it is/how easy is to find a job/etc, why JS? What are the strong points which make it a better language than lua/python/lisp/tcl/ruby? Thanks.
On the server the advantage is much less clear-cut, but a lot of it boils down to “we want to use the same language for the front end and the backend“. Although in my experience this is actually a horrible idea, and tends to result in very messy code and lots of work arounds in practice.
Anyway for me personally I continue to use JavaScript because of a combination of wanting to build lightly-interactive webpages and because that really is what the job market demands. So many companies are dead-set on hiring someone with node, react, and whatever other JavaScript experience. I tried taking it off my resume at one point because I kind of hate it, but if you’re at all involved in full stack web development it’ll really hurt your career if you don’t do JavaScript.
Helpful resource: http://callbackhell.com/
But seriously, calling it 'modern' is pointless. It's not adding anything valuable and its just going to become out of date (and thus wrong).
OTOH out of scope are server-side JS (NodeJS), transpilers like babel, bundlers like webpack, and of course package managers like npm and yarn
- for in loop - for of loop
as a couple examples, and those have been around for at least a few years now. There's probably more missing too. To what the above person said. The usage of "modern" or "latest" or similar is going to fall behind and make for bad searching.
It's 2020 and you still use loops? ;-)
That eslint rule is a good example of a cargo cult. The second link in its rationalization argues for using underscore over touching a dangerous loop yourself.
The guide might come to lack some newer things over time, but I doubt those will include any major paradigm shifts, because the past ~10 years have likely been the most dynamic that JS will ever see in terms of idioms and best-practices. JS made a radical shift into a mature language, and now it is mostly on the other side of that transition. So writing a "modern" (post-transition) tutorial makes perfect sense to me, and I don't think it will become irrelevant any time soon.
Can you help me debug why `document.createElement('button').attachEvent('onclick', e=>alert('attachEvent!'))` isn't working then?
You might object that DOM APIs aren't part of JS proper and that's true, but this guide covers `addEventListener` on this page: https://javascript.info/introduction-browser-events
Sticking only to JS language features, I assume you can help track down why my `with()` statement doesn't work. Or why `function testing() { console.log(this.location.href); } testing();` throws an error but only if I package my code as an ES Module instead of an AMD bundle.
I agree that breaking changes like this are increasingly unlikely to happen, and I think the changes that have been made are easily net positive. But the claim that they never happen is simply not true.
I'll refine my statement to "The JS standard never introduces breaking changes".
attachEvent never was part of any standard, and is therefore subject to breakage. Non-standard APIs should never be part of a comprehensive guide to the language in the first place.
The `with` statement is described on page 75 of the ES3 standard[0]. It does not work in an ES Module or in a strict mode context. This is a breaking change.
But when most people say "breaking changes" they mean things that suddenly cause legacy code to stop working, and non-strict mode will almost certainly be supported ad infinitum, so I don't really count that. It's also almost certainly never going to happen again.
Here's a simple question to ask yourself: what if non-IO operations allowed you to use the .then() syntax? If you have the choice to use:
1 + 1.then(function(result) { ... }
vs const result = 1 + 1
Which would you choose?It doesn't seem unreasonable to use then() to express: "Run this anonymous function whenever the async thing completes. Meanwhile let's do this other stuff right now."
However, when you want a more fine-grained concurrent execution of different asynchronous things, then() still could be very useful.
const task2then3 = async () => task3(await task2());
const [result1, result3] = await Promise.all([task1(), task2then3()]) async function getResult3(){
const res = await task2()
return task3(res))
}
const [result1, result3] = await Promise.all([task1(),
getResult3()])There's also other useful utilities such as Promise.all(), Promise.any() and Promise.race().
One problem. I’m increasingly coming across devs who’ve never used Promises directly, only async/await. They’re introducing all kinds of problems into code because they don’t have that foundational understanding of Promises. I think it’s essential to know how Promises work, even if we generally recommend async/await.
Also, Promise interface can do things that async/await cannot, such as Promise.all, and other unusual async execution scenarios. It’s important to have those tools in your belt.
PS I should clarify await and Promise.all/any work fine:
await Promise.all(items)No, because you might have to write explicit promises in the browser with async API that are callback based.
You need to understand how promises work to use async/await at first place anyway.
Just like it's better to understand how prototypal inheritance works in JS BEFORE even using a single class declaration.
About that, does JS class inheritance now work like classes in java for example? Or is it still just syntactic sugar for the prototype inheritance? By your wording, I assume the later?
https://stackoverflow.com/questions/36419713/are-es6-classes...
(async () => { set(await get()); })();
get().then(r => set(r));
Ignoring error handling I'll often choose the second option. get().then(set)
It's the try/catch blocks that make async/await truly worse than native promises. I use them sparingly because so often the .then syntax is both clearer and terser. get()
.then(handleResult)
.catch(useFallbackResult)
.then(updateState)
I prefer concision and functional expressiveness because it reduces the surface area for writing buggy code. Much like how using map instead writing a for loop can eliminate out of range index bugs, chaining promises brings useful guarantees about how the code I do write can be interpreted. const result = await get()
set(result)
But you do you.Current node and console have top level await BTW.
In other words, your complaints have disappeared in node, and will soon in browsers: https://github.com/tc39/proposal-top-level-await
So yes:
set(await get())