[HN Gopher] How JavaScript Works: deep dive into call, apply, an...
       ___________________________________________________________________
        
       How JavaScript Works: deep dive into call, apply, and bind
        
       Author : zlatkov
       Score  : 49 points
       Date   : 2021-07-08 12:19 UTC (1 days ago)
        
 (HTM) web link (blog.sessionstack.com)
 (TXT) w3m dump (blog.sessionstack.com)
        
       | bluepnume wrote:
       | Call, bind and apply should be discarded and forgotten about,
       | they add too much confusion, there are better ways, and they end
       | up being used as terrible interview questions.
       | 
       | Incidentally, we should also discard `this`, unless directly
       | inside a class method.
        
         | ubaltaci wrote:
         | that list should also include anything that touches prototypes
        
         | hajile wrote:
         | There is literally NO substitute for either call or apply as
         | they are low-level JS primitives. Arrow functions can go a long
         | way toward handling .bind() scenarios, but I believe there are
         | situations where you must still use .bind() to prevent
         | constantly creating new functions (and the related garbage).
        
         | kecupochren wrote:
         | I've literally never used them during my 8 years of working as
         | a JS dev. Maybe I'm doing it wrong.
         | 
         | Edit: actually I did use .bind with React before arrow
         | functions came
        
           | hajile wrote:
           | Until for..of came around,
           | `Array.prototype.map.call($nodeList, myFn)` was pretty much
           | _the_ way to iterate over things that were  "array-like" but
           | didn't actually inherit from Array, so didn't have such
           | methods.
        
           | nicoburns wrote:
           | They were pretty widely used (especially in library code)
           | before arrow functions were added to the language.
        
         | jenseng wrote:
         | You get "clean and DRY" at the expense of "not beginner-
         | friendly" and "you need be to very careful".
         | 
         | Thanks, but no thanks. I'll take clear, understandable code
         | over clever footguns any day.
        
         | jollybean wrote:
         | I came here to write exactly that.
         | 
         | There was once a time when such 'js ninja' skills were
         | appropriate, but now they almost represent an anti-pattern in
         | normal usage.
         | 
         | For some kind of framework, maybe.
         | 
         | But otherwise, they're just going to cause problems and they
         | don't really provide something really valuable wherein another
         | more basic use case wouldn't be better.
         | 
         | A pragmatic approach might be to 'stick to a solid version of
         | Typescript' and even then be wary of the fancy stuff unless
         | it's truly needed. (Say, you're building a lib or some core
         | module).
        
         | user3939382 wrote:
         | I figure there's 3 possibilities: I'm just dumb, I don't use it
         | enough, or JavaScript is poorly designed. For some reason, even
         | after 20 years of using JavaScript on and off and reading a
         | dozen books about it, I can't articulate exactly how the
         | language works, how scope is evaluated, the composition of
         | objects and prototypes which has some kind of turtles-all-the-
         | way-down thing going on with it. When I read explanations in
         | books it's like hmm ok.. I guess that makes sense. Then a week
         | later I don't remember. The languages I've spent the most time
         | with are SQL, PHP, Bash, and Clojure, and I never felt that way
         | about them. Maybe it's just me.
        
           | wruza wrote:
           | I also had this trouble, bevause for all other languages you
           | can just tead the spec once and that's it. But ES specs are
           | too technical to be used as such. After few years I just read
           | non-boring parts of ES6 and it cleared all dark corners.
           | 
           | I'd say _all_ of the articles on the internet are rehashing
           | the spec in (at best) a dubious and ritualistic way, and have
           | zero technical value if you ask me.
        
           | nicoburns wrote:
           | Prototypes are quite simple. An object _may_ have a
           | prototype. If it does then that prototype is just another
           | object, which is considered the first objects parent (which
           | works with method calls like class based inheritance). The
           | chain ends because it 's also possible for an object not to
           | have a prototype.
        
         | normac2 wrote:
         | > Incidentally, we should also discard `this`, unless directly
         | inside a class method.
         | 
         | When you say it has to be "directly," do you mean we should
         | never use arrow functions (or use them only for looks)? Since
         | the purpose of those is to add "this" support to inner
         | functions?
        
         | cj wrote:
         | > should be discarded and forgotten about, they add too much
         | confusion
         | 
         | How does it add confusion?
         | 
         | Bind, call and apply are fairly straightforward and not
         | difficult concepts to grasp for any mid to advanced level JS
         | dev and they're useful in many scenarios (although bind is less
         | useful / less needed now that we have arrow functions, but call
         | and apply are definitely not something to be "discarded").
        
           | Arnavion wrote:
           | `call` and `apply` can also be replaced with arrow functions
           | and splats.
        
             | hajile wrote:
             | How would you replace the classic
             | `Array.prototype.map.call($nodeList, myFn)` with arrows and
             | splat?
        
               | Arnavion wrote:
               | If the goal is to call functions on things whose
               | prototype does not define them, then yes arrow functions
               | cannot replace `call` and `apply`. They can't replace
               | `bind` in such a situation either, but the precondition
               | of this subthread was where `bind` _can_ be replaced with
               | an arrow function, ie the bound function is being called
               | on the same `this` in the first place.
        
               | guntars wrote:
               | You should forget about that too. It's applying a
               | function from one object to something else that it wasn't
               | designed for. It happens to work in this case because
               | $nodeList and Arrays are both array-like, but that's a
               | lucky happenstance.
        
               | nicoburns wrote:
               | You could do it like this:                   const
               | mapNodeList = (...nodeList) => nodeList.map(myFn);
               | mapNodeList(...$nodeList)
        
               | hajile wrote:
               | That creates an entire extra list of garbage.
        
               | chrisseaton wrote:
               | Doesn't the compiler optimise it away?
        
               | hajile wrote:
               | Those aren't the same types. One is a DOM array and the
               | other is a JS array. They don't share the same
               | constructor or the same prototype chain.
        
               | Jcampuzano2 wrote:
               | You can do it without either of those with this:
               | 
               | Array.from(nodeList$).map(myFunc)
               | 
               | or if you want to spread
               | 
               | [...nodeList$].map(myFunc)
        
               | hajile wrote:
               | That creates a new array that must be GC'd.
        
               | Jcampuzano2 wrote:
               | Sure if you want to get nitty gritty, but you just asked
               | how to replace it in the context of someone saying you
               | can go without call and apply, which both of these do
               | with the same input and output.
               | 
               | Unless your nodelist is insanely large, this is going to
               | be a trivial GC to perform.
        
       | monus21 wrote:
       | My one annoyance with these is that they aren't supported in
       | Typescript i.e no return types.
        
       | yawaworht1978 wrote:
       | How much call, apply and bind is abstracted away in reactjs?
       | 
       | I also agree that the assignment of "this" is pretty difficult to
       | grasp, especially in large codebases with callbacks, fn as
       | arguments, and the issue still remains, despite fat arrow
       | functions, async/await and promises. Someone mentioned
       | prototypes, that's a double edged sword, it can help to have own
       | prototypes but it can cause so much confusion.
        
         | Jcampuzano2 wrote:
         | apply/bind/call aren't really abstracted away at all in react.
         | In older versions they did do the binding magically for you,
         | but when they made the switch to es6 classes they stopped doing
         | that in favor of writing JS more like vanilla JS with less
         | magic, outside of JSX of course.
         | 
         | Now with hooks/function components being the most common way of
         | writing apps, there's almost no need for binding or dealing
         | with "this" at all.
        
       | peanut_worm wrote:
       | I have probably used these functions only a handful of times
       | since ES6 came out
        
       ___________________________________________________________________
       (page generated 2021-07-09 23:00 UTC)