Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Modern JavaScript Tutorial (javascript.info)
538 points by Hbruz0 on May 15, 2022 | hide | past | favorite | 101 comments


In almost 10 years of professional development with Javascript/Typescript, I have never encountered a colleague using the call/bind/apply keywords (or "this" outside of classes). I'd say almost all professionals deliberately avoid 80%+ of the language in practice.


Yeah, `call` got supplanted by `bind`, and `bind` got supplanted by arrow functions. `apply` got supplanted by spread parameter syntax.

I've used them before for doing stupid reflection hacks (literally just used them today to build a debug UI where I can make sliders out of objects), but it's not code I would really want to ship in production.


For the benefit of anyone who doesn't have a lot of experience with call, bind and arrow functions ()=>{}. No, these don't supplant one another and are separately useful in various ways. Reading the linked articles shows some of the related situations.


No. Bind creates a new function, call and apply do not.


More specifically, bind creates a new function + context, that you can hold a reference to and reuse, but you cannot do this with call or apply.


In practice though, many places that used apply/call tend to bind instead.


apply and call invoke a function with a specified receiver object, and arguments.

bind creates a new function that is bound to a specified receiver.


One of the most common places front-end devs encountered call/apply was when binding functions to event handlers. In those cases an anonymous function was often generated which used apply or call. Bind replaces this dance for many cases. Hence, most cases where devs encountered js call/apply were replaced by bind. There are differences between the two, but they largely didn't matter for most cases.


Unless you have strict performance requirements, then it does matter.


I got to use bind for a class based event handler, using arrows would bind this to the wrong context.. but maybe I'm doing it wrong.


I've used this syntax which auto-binds this, worked for me

  class Thing {
    method1 = () => {}
    method2 = () => {
      something.addEventListener('click', this.method1);
    }
  }


Fun trick. A bit tangled though


Kudos to the author ...

... but yes - a 'Modern' approach means calling out risks, or more abruptly - that which may even be considered 'anti pattern' inherent in a language as it evolves over time, with hindsight.

Perhaps the most preeminent example would be pointers in C++ - which we generally know to use with 'smart pointers'.

If C++ 'were designed today' - among other things, it'd be likely that 'smart pointers' would be 'default' and they'd be more deeply and seamlessly integrated, and 'direct memory reference' would be seen as a 'thing to do only if necessary' and a bit of a 'corner case'. Necessary, and common enough, surely as in that level of programming we are going to 'go there', however, it's something we wouldn't see as normal practice, rather something we do but with some other idioms, APIs and conventions around it ... possibly with demarcations of 'unsafe' a bit like Rust.

I think it's important, because these are precisely the things that young developers may become entangled in. It should be more like: "By the way this is how this works, but you may want to think twice about using it, here are some cases where it might be 'ok', here are some cases where it's not".

But I don't want to take away from good authorship either, we depend a lot on people stepping up to the plate and doing this work. As an aside, it seems almost perverse that 'Big Corps' just don't do this themselves. I mean, if AWS uses JS extensively, it'd seem reasonable (even from a selfish perspective) for them to 'just do' a comprehensive, JS set of docs.

It's weird that the world depends on 'a few nice dudes/dudettes' to maintain something like 'caniuse.com' and the plethora of other such important works.


> Perhaps the most preeminent example would be pointers in C++ - which we generally know to use with 'smart pointers'.

Smart pointers are nice and all that but I have yet figured out how to mix them with code which doesn’t use them which is like 99.9% of all library code.

Not to mention that interfacing with C code (like python extensions) are basically impossible unless the calling code is responsible for the object lifetimes. I don’t know how language de jour deals with this C interop but have read it is a pain point almost universally.

Even some of the newer languages I see posted here have manual memory management as the default.


>how to mix them with code which doesn’t use them which is like 99.9% of all library code

That's what the "more deeply and seamlessly integrated" would be mostly about.


> 'smart pointers'

I tends to avoid smart pointers. There are too many variants, supported in different c++ version. Can't reasonably track which one is supported in which compiler


Huh? It's literally just std::unique_ptr for most uses, available since c++11.


Almost every C++ framework since the mid-90's has some variation of them, and those haven't gone away in existing code.


Yes, it's a bit my point.

They are a messy bandaid.

The notion of using them in lieu of 'nothing' is rational - but the application is a mess.

We need a clean version of C++ that's not some gigantic new thing.


Avoiding smart pointers for those reasons is a bad idea.

Smart pointers are unified since C++11 standard with support in all modern compilers for various platform. Invest some time to get familiar with them and you will not regret.


80%? Really? I don't feel like call/bind/apply are 80%. More like 1%. What's the 80% of unused features you're referring too?

Now, not using 1% of a language seems common. There are plenty of parts of C, C++, C#, Java, Python, etc that I rarely run into.

On the other hand, for testing, mocking, polyfilling, etc call/bind/apply are invaluable.


On the other hand, for testing, mocking, polyfilling, etc call/bind/apply are invaluable.

For writing libraries to do those things call/bind/apply are useful, but most developers aren't doing that very often.


Re-reading the table of contents of this tutorial, no, probably not 80%. But if it isn't 50% it's close.


They are very useful at the framework level, if you do much work with vanilla JS at scale they become useful for applying generic functions against various scopes.


Which makes reading framework code so much harder IMO. There are many constructs in good framework code that you very rarely see as a 'regular' JS developer. Sometimes even understanding where the entrypoint really begins in node_modules can be a challenge.


A lot of laziness has come from these newer rest/spread syntaxes (something to do with functional programming patterns too?).

As a oldschool Amiga/PCDOS/ASM/C developer who moved on to the web ten years later... it always feels awkward to me to do things like arr = [...arr, ...arr2] because I'm always wondering just how effectively that is handled by the Javascript compiler.


On a technical side, ubiquity of javascript ensures that performance of common cases will be looked at and improved, if not yet.

But as a fellow former low-level, my humble advice is: stop worrying and write clear code. Clear code eventually will run fast and stay clear. Nuanced code eventually will run as fast but stay nuanced.


Readability and pragmatism always win.


Probably more effectively than anything you could roll yourself.


Not every tool a language offers should be used in your normal day-to-day dev work. Doesn't mean it's useless. I'm writing a dependency-less CLI tool with Node and just have used apply - super helpful ;-) I've also used it a lot when I wanted a dependency-less GraphQL server...


Which is great. Mozilla does the same thing with C++. No reason to use complex footguns for simple tasks. Obviously there are use cases but mostly not for 90% of CRUD front end devs.


> Mozilla does the same thing with C++.

To be fair, C++ is the epitome of a language you only adopt after consciously picking a very specific subset of features, or explicitly marking features as verboten. Template metaprogramming and exceptions are perhaps two of the most popular features that are routinely banished from C++ projects.


Yeah, because they're probably using libraries that are heavily using those keywords under the hood, in order to supply functions with the correct 'this' context.


That doesn't change the fact that if you're not a library author you should probably avoid using that feature. It's not that the feature shouldn't exist, it's that it's now best used in plumbing code, not in application code.


I think you are imagining a dichotomy of use cases that doesn't really exist. Not everyone is writing software by gluing libraries together, and so there are still plenty of uses for it outside of libraries.


Relevant: "How (and why) developers use the dynamic features of programming languages"

<https://doi.org/10.1007/s10664-012-9203-2>

<https://users.dcc.uchile.cl/~rrobbes/p/EMSE-features.pdf>


""How (and why) developers use the dynamic features of programming languages: the case of smalltalk""

https://www.inf.unibz.it/~rrobbes/p/EMSE-features.pdf


Huh?


I just didn't see that the second URL was the pdf.


Thanks for sharing this! In the last couple of years I've moved from being primarily a Java developer to a nodejs developer and I love exploring what dynamic languages bring to the table.


I'm not sure that attitude is the right takeaway from the paper I linked.


As someone who likes functional programming, I appreciate .bind as a reasonably convenient way to do partial function application.


One thing I didn't get about functional programming is planning the parameter order in advance for currying them later. Arrow functions may not look as neat as Haskells currying, but you can partially apply any parameter regardless of whether it's first or not, including separate properties of object parameters.


Defaulting to data-last gets you 80% of the way.

    fn = (a -> b) -> a
So your typical array mapping becomes

    list.map(to(v => v * 2))
All very contrived of course.

Ramda’s currying [0] gives you the _ param to play with the order. But I’ve come to the conclusion that currying in JS is rarely worth the effort. [1]

0 - https://github.com/ramda/ramda/blob/v0.28.0/source/__.js

1 - https://2ality.com/2017/11/currying-in-js.html


.bind seemed to be an idiom in early React before we had the arrow functions. I also remember it coming up a bit in older frameworks like Knockout.


.bind doesn't really have a lot to do with frameworks specifically, except maybe just that the docs may have been the first time folks were introduced to those features of the JS language.

That said, I did use it a TON in the jQuery days (event handlers).


Used bind a whole bunch in the knockout days and you will still find bind in a lot of todays react docs if I’m not mistaken.


Definitely not "a lot" - searching the existing docs, I see a mention in the FAQ at https://reactjs.org/docs/faq-functions.html#how-do-i-bind-a-... , but not really elsewhere.

Also, the new React beta docs at https://beta.reactjs.org teach function components rather than classes, and thus there's no use of `.bind()` at all.


As someone that uses them from time to time, I have then had to then explain to colleagues what they are doing (and yes I consider this when I use it, whether that is worth the tradeoff).

Personally, I like to extract larger arrow functions and I am a fan of traditional function declarations in some situations over `const x = () => {}` style function assignment (I feel the latter unnecessarily clutters up code above the logic of the specific component, service or module since it must be declared prior to being used.) Those preferences do lead to needing an understanding of bind, call and apply. Or maybe understanding bind, call and apply lead to me feeling comfortable using those patterns?

Edit to add a bit of history: I started doing this when writing a fair amount of jQuery with a lot of event handlers. And while anonymous or arrow functions worked, the code was soo much cleaner when you put the handler functions below the regular logic. If someone wants to see what a handler function does, it's easy to go down and look, but otherwise, a good name is all that is important. These days, I follow similar patterns, extracting code that doesn't need to be inline into a function that can be referenced as needed, but doesn't need to be inline in the code all of the time.


I'm currently working on a game[0] similar to Untrusted[1] and I had to use bind (among other techniques like variable shadowing) in order to "sandbox" player provided code from interfering with other game objects or accessing the global scope (obviously there's no perfect sandbox, but it at least it makes it more difficult for players to do naughty things). Bind is useful because you can control the meaning of "this" when evaluating user-provided code, and I use it to deny player access to the parent scope by calling bind(undefined).

[0] https://www.bryanpg.com/games/pragma_twice

[1] https://github.com/AlexNisnevich/untrusted


Have you considered running "untrusted" code in a worker? That way the code can not interfere with the global scope.


Indeed, however, I started this project a few years ago before I knew about workers and so it would be a lot of effort to switch now. Perhaps if I make a follow on game I'd try workers. I'd have to implement message routing in order for objects to communicate with each other and I'm not sure how much impact that would have on performance.


I highly doubt that. All of those used to be extremely common before arrow functions.


You used them when your framework/library documentation or SO told you to, but way less deliberately.


> I'd say almost all professionals deliberately avoid 80%+ of the language in practice.

I don't think is a specific thing of JS. The same happen with almost any language, product features...


I concur. I have been programming JavaScript for 20 years and I have never used call/bind/apply. I have never been able to understand what they are for or what they do.


I also deliberately avoided using them as they (IMO) belong to the "bad parts", or at least the parts that most mortal frontend devs don't need to use outside of interviews.

With frameworks, it's easy to avoid them and unless you write lots of vanilla or you roll your own framework, they just don't come up, and therefore I expect my colleagues (and me) to just mess things up when we try to use them.


This used to be super common when events were more widely used


This used to be much more common in es5. It’s good to know how they work etc and why they were a necessary evil way back when.


Which issues do these methods cause?


None. It’s just the GP is somehow complaining that just because they didn’t see them they’re not useful.

I saw .call just a few hours ago because until recently it was the safe way to call hasOwnProperty[1].

    1: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty#using_hasownproperty_as_a_property_name


This is excellent. I think https://www.internetingishard.com/html-and-css/ complements it well as an introductory tutorial to HTML/CSS.


Agreed! I wrote a related blog series on "How Web Apps Work" after years of trying to teach web dev to Java/C++ devs, or seeing beginners ask questions because they had no idea what any of these things are in the first place. That series tries to explain the key pieces of web dev concepts, terms, and technologies, and how they fit together, and provides an overview of HTTP and servers, client dev, browsers / HTML / CSS, JS / DOM, and AJAX:

https://blog.isquaredsoftware.com/series/how-web-apps-work

The "Interneting Is Hard" HTML+CSS page is one of the best intro resources I've found for those topics, as is the "Modern JS Tutorial", and I specifically linked those as recommended resources from the related posts I wrote.


The only thing I want is a proper tutorial or book on how to debug and trace a modern web app.


I wrote a sibling comment about some web app fundamentals posts I've put together, but fwiw I've also got some resources on debugging as well. This is another topic that seems to be rarely taught, and people just have to pick it up through hard-earned experience.

I did a presentation last year that provided some general guidelines and suggested approaches to debugging, as well as specific info on the standard controls used in GUI debuggers and tips for debugging React and Redux:

https://blog.isquaredsoftware.com/2021/06/presentations-debu...

I also have a prior post where I gave some general debugging tips, and wrote up several "war stories" of weird and difficult problems I've debugged:

https://blog.isquaredsoftware.com/2019/01/blogged-answers-de...

You mentioned "trace", and I'm not sure if you're referring to "trace a request as it gets passed through multiple services", or just "trace data flow on the client side".

The other resource I can point you to: a couple months ago I joined https://replay.io , and we're building a time-traveling debugger for JavaScript apps.

The basic idea of Replay: Use our special browser to make a recording of your app, load the recording in our debugger, and you can pause at any point in the recording. In fact, you can add print statements to any line of code while debugging the recording, and it will show you what it would have printed every time that line of code ran!

See https://replay.io/record-bugs for the getting started steps to use Replay, and https://docs.replay.io/docs/examples-d25ae319114e4d109022458... for some videos and examples of using Replay to solve problems.

We're working on additional features to help with debugging apps - we already have the React DevTools integrated into our debugger, so you can inspect the component tree at any pause point, and over the last couple weeks I got the initial alpha implementation of Redux DevTools integration working as well. (Long-term, we'd like to integrate _all_ major framework-specific DevTools as well.)

Beyond that, we also spend a bunch of time helping teach people how to debug in general, specifically _because_ that's a thing that is so rarely taught.

If you've got questions about Replay, or just want to chat about debugging approaches, come by our Discord at https://replay.io/discord and say hi - we'd love to offer suggestions!


No offense but this seems like a bunch of blogspam with some basic slides about basic debugging, and then an advertisement for your startup. Hardly comprehensive or insightful.


Sure, I'm mentioning the company I work for intentionally, but that's specifically because we make a tool that is designed to help make debugging easier :) And the slideset also seemed like it matched what you were asking for.

FWIW, given the number of presentations I've put together and articles I've written [0], and the amount of effort I've put into all that material over the years, I don't think my work qualifies as "blogspam".

But, if you feel the material in that slideset is too basic, I'm genuinely curious: what info about "debugging modern web apps" _are_ you looking for, in that case? If there's some particular topics or ideas that aren't well covered, I might be able to put together something that would help fill that gap.

[0] https://blog.isquaredsoftware.com/series/presentations/


As far as Javascript books goes this looks pretty replete, kudos to the author!

I will add it to my bookmarks to recommend to new developers alongside the excellent Eloquent Javascript [1], which for all I know probably is missing some things between when it was written and now which this modern javascript tutorial seems to cover. Very cool!

[1] https://eloquentjavascript.net/


The modern JS tutorial is indeed a very good and comprehensive resource.

For all its qualities, Eloquent JS is not a very beginner-friendly book. For a smoother learning curve, you might consider https://github.com/thejsway/thejsway.

Disclaimer: I wrote this book.


FYI, you link to https://bpesquet.fr/ both on that page and on your HN profile but your server isn't listening on https/443 (works on http/80).


Corrected, thanks for pointing it out.


The OP (javascript.info) and Eloquent Javascript go great together - I used these two together all the time. Eloquent Javascript is great for deep dives into select topics and is well-written. OP is great as a reference guide while you're writing code.


Some previous discussion from 2020: https://news.ycombinator.com/item?id=25333350

This site is IMO the best reference out there for modern JS/DOM fundamentals. It's concise, clear, consistent, accurate, and well-organized throughout, which is no mean feat for how many topics it covers.


Most of the areas I checked out looked great, but... the section 3.4 on 'Ninja code' is terrible:

It swaps to an ironic, sarcastic, in-jokey tone almost completely divorced from the previous sections that will leave much of the intended audience (people new-ish to programming) utterly confused by what is being said—or in this case, worse, what is intentionally not said. The effect of this self-absorbed style of teaching is so poor, I think, that that page actually damages the overall text in its current state.

Surely the point of a site like this shouldn't be shaped for the entertainment of experienced programmers, but to help less experienced programmers know what to do—and what not to do. They could still make it funny, just... not that.


That's the joke.


Thanks! Macroexpanded:

A Modern JavaScript Tutorial - https://news.ycombinator.com/item?id=25333350 - Dec 2020 (292 comments)


Is it better than MDN's own tutorials or references?


ninja code!

https://javascript.info/ninja-code

I get it's a list of bad practices and it's kind of funny in an "inside joke" kind of way but if you're reading the site to learn JavaScript then you are probably not on the "inside" yet?

As funny as it is for those "in the know" would it be better as a list of "don't to X (bad examples) do Y instead (good examples)? As it is there are no good examples, just a cryptic joke.


Agreed, needs a big disclaimer at the top imo


Some of the practices aren't even bad. Adding an underscore or two as a bad practice? One is well-known convention for stuff you don't want touched and even JS itself uses double underscores for some stuff.


I am proud to be contributing to Turkish translation of this project.


Self learning JavaScript and this site has been a huge help.

I’ve actually set up Alfred such that when I type “j [search terms]” in to its search bar that it opens a new tab with that search in JavaScript.info because I was doing “site:JavaScript.info” in google so frequently.


Might be a dumb question, but anyone got a similar tutorial for TS?



Preparing to interview with JavaScript. This is helpful, thanks!!


having just gone through that, my pro tip is: look at implementing promise.all() as well as extending the code to have a limit on concurrent promises/etc. very popular question.


Thanks for this! Could you please share any other tip if any?


Closures, event bubbling, event loop: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Even...

Basically all the things you otherwise forget about or never need to worry about when writing production JavaScript. Yawn. I sound like a curmudgeon and I am: too many interviews I've been in that involved JavaScript felt like abstracted garbage. Nevertheless, good luck!


have a really good way of talking through how you handle async code and the difference between async and procedural code. Plus, how you can make async code read like procedural (async/await). I always give bonus points if you can describe clearly the difference between using ansync/await and then based promise code (not just saying "syntactic sugar", but actually explaining how the code looks different but yet how they are effectively the same).

How people answer questions around promises in general often gives me a good idea of where they are at in their JavaScript journey.


Bruh, this is so good!

In just a few minutes of reading, I got cleared up on a few things.

For reference, I dabble in Javascript just to do small things that are incidental to my main programming languages.


I also recommend checking out https://learn.javascript.ru/ which has more content than the english version (same author though I believe).

Install https://addons.mozilla.org/en-US/firefox/addon/traduzir-pagi... and let the learning begin.


Is there a list of equivalent excellent resources for other languages? I'm familiar with JS and Python - I'd love to get up to speed with other languages this way.


For PHP - https://phptherightway.com

Like JS, PHP has alot of old, outdated practices which aren't considered best practice anymore. Lots of this type of code will show up in search results in google when you search for solutions to common problems.


For Go start with A Tour of Go (https://go.dev/tour/welcome/1) and then read Effective Go from start to finish (https://go.dev/doc/effective_go) and you'll have a very good grasp of the language. Both are extremely high quality and maintained by the core language group/team.


For me this is a great supplementary resource to the MDN docs.


Great resource which I'd like to use, I only wish the search would work like a command palette like on MDN or Tailwind docs... because if this is so complete this could be a great alternative for me from MDN, having more "tutorial" text and examples, not just specifications.

So I'd like to be able to hit Cmd P or Ctrl K or the like, enter "nullish" and then find the article on nullish coalescing op.


Just bought its PDF version to show some support, it's a decent site for JS indeed. I use another site more often though at https://www.javascripttutorial.net, which is not as deep as this one, but way more concise. It's kind of like w3schools, not the best authoritative site, but, nothing beats its simplicity.I support all of them.


I love the design of the site. Very clean and good use of available space.


This looks really good


Ask Douglas Crockford to review this? :-)


hi , i love your content . it is so organised and has everthing for a new begineer.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: