New, Apply, Call, Bind in JavaScript
In JavaScript, apply
, call
, bind
are crucial concepts for development, which all relate closely with this
pointer.
I’m gonna start with a few questions:
- What does
new
actually do? - Difference among
apply
,call
andbind
? - How to implement an
apply
orcall
?
Well, let’s get started!
New
The main function of new
is to execute constructor functions and return a new instance.
Let’s check out a demo:
1 | function Person(){ |
Easy enough, we call new
on constructor Person
and get a new instance of Person.
Let’s break down what new
had done during the above process:
- Creates a new object
- Assign the scope of the constructor to the new object (or say
this
binding) - Execute the constructor function
- return the new instance
What happen if we don’t use new
for the same process? Let’s try.
1 | function Person(){ |
See? We don’t get a new object back p
. Instead, the this
during the execution points to the global window
object by default, which allows us to call name
without explicitly declaring it.
One step further, if the constructor returns a object, how would things change with new
?
1 | function Person(){ |
Obviously, new
doesn’t create a new object. It returns the object straightly.
But, if the constructor returns non-object value, new
works as usual.
1 | function Person(){ |
Therefore, we can conclude that after new
we always receive a object, either new instance or object that returned by the constructor.
Apply & Call & Bind
apply
, call
, bind
are three methods of function
. Let’s take a look at a demo:
1 | func.call(thisArg, param1, param2, ...) |
The common usage of these three is to change the this
of the function
, i.e. the execution subject. thisArg
refers to the this
object you want to call on.
Difference for the second param among them:
apply
receives an param arraycall
andbind
bypasses param from position 2 to Nbind
would not execute the function immediately, it would return a new function with a changedthis
.
What are all these for? Reusage! Say, we don’t have to buy a house for living if we can rent one. Same here, we borrows functions from existing objects, saving spaces and efforts.
Let’s take a deeper look for the usage and everything should be clear:
1 | let a = { |
Classic scenarios
Let’s see what we can do with these three BORROW ablities.
Type Checking
Remember how we use Object.prototype.toString
for checking variable types. There it is.
1 | function getType(obj){ |
Array-Like Value
We can have an array-like value if we define our object as:
1 | var arrayLike = { |
But sure it has no array methods. No worry, we can borrow from real Array!
1 | Array.prototype.push.call(arrayLike, 'jack', 'lily'); |
We just pushed a new value into the array-like object by calling Array’s push! Isn’t that magical?
Get max/min of an array
Check this out: we can pass an array and get its max/min value by using Math.max
/Math.min
:
1 | let arr = [13, 6, 10, 11, 16]; |
Inheritance
Back in the previous article 6 Ways of Inheritance in JavaScript, we use Parent.call(this)
inside a child constructor for inheriting the properties from parents.
Can we implement then on our own?
Try new
Let’s do a quick recap about what does new
do during execution:
- Allows instances to visit private properties
- Allows instances to visit the properties on constructor’s prototype chain. (
constructor.prototype
) - Return a reference type data (either new instance or result of constructor)
Here is our version:
1 | function _new(ctor, ...args) { |
Try apply
and call
The principle of apply
and call
is similar, let’s implement them together!
1 | Function.prototype.call = function (context, ...args) { |
The key is to use eval
to execute the function itself in a different context (or say on a different object).
Try bind
The basic principle of bind
is also similar, but bind
doesn’t execute immediately, so we don’t need eval
anymore.
1 | Function.prototypeFunction.prototype.bind = function (context, ...args) { |
The key here is to return a function with a changed context. Also we can’t lose the prototype in the new function.
Sumamry
Let’s do a summary for the three methods:
Method | call | apply | Bind |
---|---|---|---|
params | multiple | one array | multiple |
function | change this for a function |
change this for a function |
change this for a function |
result | immediate execution | immediate execution | return a function |
implementation | call eval |
call eval |
indirectly call apply |