There’re three similar methods in Function.prototype, call, apply and bind, these three methods could change the dynamical `this` in function, I’ll not talk too much about `this`, but more about these methods’ ins and outs.
So, in this article, I’ll do compare with a(apply) / b(bind) / c(call), and little bit concept of function `this`, in last, will take a practical use case about self, bind, arrow function.
Let’s start our trip.
Why we need apply / bind / call ?
Let’s see the common use case of apply / bind / call:
You’ll get the same output, these three can do the same thing as L8–9.
Please tell me what’s the magic behind these three methods!
Let’s classify to call, apply vs bind :
- call, apply return function result
- bind method return the function with binding `this`
We can figure out that bind method doesn’t wanna call the function.
The usage of Function.prototype.call()
call()method calls a function with a given
thisvalue and arguments provided individually. （src. MDN）
Honestly, I do not really understand it when I first saw this…
As my words, we can just shift the `arguments` to right, and tell the function `this` what we wanna use in the first parameter.
Except the first parameter, it’s 87% similar as original function call:
func(1, 2, 3) vs func.call(null, 1, 2, 3)
So, Function.prototype.apply() is just a shortcut
The interface of
apply() only receive two parameters, you know the first one (yup, `this` again), and the second one is the arguments but it’s array.
func( 1 , 2 , 3 ) vs func( null , [ 1 , 2 , 3 ] )
A special point, there’s a preserve variable `arguments`, it’s array, so if you use `apply` method, you don’t need to do destructuring assign :
Just said, in the upper use case, we can easily solve that using `bind`.
When you search on web, you’ll find out there’re thousands article wanna tell you how awesome you can do `currying` with `bind` method, why it’s a good practice, bla bla…
Let’s deep dive in bind, what bind want to do.
bind — different from the upper two, we don’t need pass the function’s parameter, and it’ll not return the result either, it’ll return “A function with the fixed this what you pass”, yes fixed, when you do, you cannot change the function `this` anymore.
In L6, we bind the function
wtf_bind_window first, so this function use the fixed this — window, you cannot change anymore even call, apply, or do bind again.
Do you really need bind()?
This is a classic case, you might have seen that when you make a callback function in class:
When you running the `laterHello`, the timer callback cannot get the correct this (which should point out to class instance), you can see it’s a very common case in Node’s class and React / Vue ’s class component.
There’re 3 ideas to solve this, `bind` is the one, but not the best one:
1 Self — something the JS developer love to use in class…
When you maintain the legacy project, you’ll see this most time.
Why I put it in the first one? Since it’s the low thinking cost solution, just use self, just follow the original pattern, no magic, no error, and easily review.
2 Binding — yup, so after reading this article, you have another choice
In this solution, there’s a big advantage of it, you don’t need to do any change in the inner callback function, but just tell what’s the correct `this` you want to apply.
In real world you don’t want to do much change but just reuse the function in callback, it might has much `this` you need to update to `self`.
But there’s another solution after ES6.
3 Arrow function — ikr, you don’t want self, but bind is hard to learn.
In most cases, arrow function has no difference from normal function, the only special is, the function `this` of arrow function always point out the context scope, and it’s fixed, even you do apply, bind and call, arrow function always got the this from context scope.
I finally finish this article, the best profit of writing articles is that I could understand more clear when introducing to others, hope you guys love it!
And next time you learn something like currying or function this, you can just refer from this article, hope it helps!