[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)