Skip to content

Commit c1b706f

Browse files
committed
complete call, apply and bind method section
1 parent 31c9851 commit c1b706f

File tree

2 files changed

+250
-0
lines changed

2 files changed

+250
-0
lines changed

10-A_Closer_Look_At_Functions/README.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,157 @@ greet("Hello")("Caleb");
246246
```
247247
248248
# The Call and Apply Method
249+
250+
```js
251+
const lufthansa = {
252+
airline: "Lufthansa",
253+
iataCode: "LH",
254+
bookings: [],
255+
book(flightNum, name) {
256+
console.log(
257+
`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`
258+
);
259+
},
260+
};
261+
262+
lufthansa.book(239, "Victor Eke");
263+
lufthansa.book(424, "Michale Smith");
264+
```
265+
266+
In the example above, the `this` keyword points to the `lufthansa` object because that is where the book function was called from.
267+
268+
Let's say we have another airline that needs to reuse the `book()` method, hard-coding this will be bad practice so what we can do is store the method in a seperate function(variable).
269+
270+
```js
271+
const eurowings = {
272+
airline: "Eurowings",
273+
iataCode: "EW",
274+
bookings: [],
275+
};
276+
277+
const book = lufthansa.book;
278+
// book(23, "Sarah Williams"); // Calling the function this way wont work.
279+
```
280+
281+
We've stored the method inside a variable which is typically different from the method inside the lufthansa object, but in order to use this method on another object, we need to use the call method because the `this` points to the global scope which is undefined at this point. I.e It is no longer a method since we copied it and stored it into the book variable.
282+
283+
So how do we execute this function on either the `eurowings` object or `lufthansa` object? We need to explictly tell JavaScript what object we want it point to.
284+
285+
And to do that, there are three fuction methods we can use: `call()`, `bind()`, and `apply()`.
286+
287+
By using the `call()` method, we can pass in values we want to replace the `this` keyword with.
288+
289+
### Call Method
290+
291+
The call() method calls the function with a given this value and arguments provided individually.
292+
293+
```js
294+
book.call(eurowings, 23, "Sarah Williams");
295+
console.log(eurowings);
296+
book.call(lufthansa, 239, "Mary Slessor");
297+
console.log(lufthansa);
298+
```
299+
300+
First we define the object we want to run the method with, then we add the other arguments.
301+
302+
```js
303+
const swiss = {
304+
airline: "Swiss Air Lines",
305+
iataCode: "LX",
306+
bookings: [],
307+
};
308+
309+
book.call(swiss, 583, "Ben Shapiro");
310+
console.log(swiss);
311+
```
312+
313+
### Apply Method
314+
315+
This is similar to the `call()` method except the given arguments are provided as an array.
316+
317+
```js
318+
const fligthData = [135, "Bradley Cooper"];
319+
book.apply(swiss, fligthData);
320+
```
321+
322+
Although the `apply()` method is not really used in JavaScript that much, we can keep using the call method and inject any array using the spread operator.
323+
324+
```js
325+
const fligthData = [135, "Bradley Cooper"];
326+
book.call(swiss, ...fligthData);
327+
```
328+
329+
# The Bind Method
330+
331+
Just like the call method, the `bind()` method also allows us to manually set the `this` keyword for any function call. The difference is that bind does not immediately call the function, instead it returns a new function where the `this` keyword is bound.
332+
333+
```js
334+
const bookEW = book.bind(eurowings);
335+
const bookLH = book.bind(eurowings);
336+
const bookLX = book.bind(swiss);
337+
bookEW(23, "Steven Seagal");
338+
// ...
339+
```
340+
341+
Here we don't have to define the this keyword, just simply pass in the value we want to update.
342+
343+
Similar to the call method, we can also pass in multiple values to the bind method and a good use case is to add another argument to the function.
344+
345+
```js
346+
const bookEW23 = book.bind(eurowings, 3422);
347+
bookEW23("Victor Eke");
348+
bookEW23("Martha Kent");
349+
```
350+
351+
This allows us to set in stone certain arguments. This method of setting argumets beforehand is what we call partial application, and what this means in simple terms is that a part of an argument of an original function is already applied.
352+
353+
A good use-case of the bind method is when we use objects with Event Listeners
354+
355+
### Bind with Event Listeners
356+
357+
```js
358+
lufthansa.planes = 300;
359+
lufthansa.buyPlane = function () {
360+
console.log(this);
361+
362+
this.planes++;
363+
console.log(this.plane);
364+
};
365+
366+
document.querySelector(".buy").addEventListener("click", lufthansa.buyPlane);
367+
```
368+
369+
This above example shows `NaN` because the handler function `lufthansa.buyPlane` is attached to the higher order function which is the `(".buy").addEventListener`, and since we know that the `this` keyword will point to the higher order function in which it was called, the this keyword in this case will be the button element.
370+
371+
With the `bind` method, we can explicitly change the `this` keyword to point to the `lufthansa` object.
372+
373+
```js
374+
document
375+
.querySelector(".buy")
376+
.addEventListener("click", lufthansa.buyPlane.bind(lufthansa));
377+
```
378+
379+
### Partial Application
380+
381+
We can also prefill default values into functions with the bind method.
382+
383+
```js
384+
const addTax = (rate, value) => value + value * rate;
385+
console.log(addTax(0.1, 200));
386+
387+
const addVAT = addTax.bind(null, 0.23);
388+
// addTax = value => value + value * 0.23;
389+
390+
console.log(addVAT(100));
391+
console.log(addVAT(23));
392+
```
393+
394+
Here we set the rate parameter of the `addTax` function to `0.23` and stored it in another function called `addVAT`. Now when we call the `addVAT` function, it will always contain the value of `0.23`
395+
396+
This may look similar to setting default values in function like so:
397+
398+
```js
399+
const addTask = (rate = 0.23, value) => value + value * rate;
400+
```
401+
402+
But the difference is that the bind method allows us to create a completely different function we can work with.

10-A_Closer_Look_At_Functions/script.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,99 @@ gretterHey("Ben");
121121
greet("Hello")("Caleb");
122122

123123
// 🔸 The Call and Apply Method 🔸
124+
const lufthansa = {
125+
airline: "Lufthansa",
126+
iataCode: "LH",
127+
bookings: [],
128+
book(flightNum, name) {
129+
console.log(
130+
`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`
131+
);
132+
this.bookings.push({ flight: `${this.iataCode}${flightNum}`, name });
133+
},
134+
};
135+
136+
lufthansa.book(239, "Victor Eke");
137+
lufthansa.book(424, "Michale Smith");
138+
139+
const eurowings = {
140+
airline: "Eurowings",
141+
iataCode: "EW",
142+
bookings: [],
143+
};
144+
145+
const book = lufthansa.book;
146+
// Does not work
147+
// book(23, "Sarah Williams");
148+
149+
// Call Method
150+
book.call(eurowings, 23, "Sarah Williams");
151+
console.log(eurowings);
152+
book.call(lufthansa, 239, "Mary Slessor");
153+
console.log(lufthansa);
154+
155+
const swiss = {
156+
airline: "Swiss Air Lines",
157+
iataCode: "LX",
158+
bookings: [],
159+
};
160+
161+
book.call(swiss, 583, "Ben Shapiro");
162+
console.log(swiss);
163+
164+
// Apply Method
165+
166+
const flightData = [135, "Bradley Cooper"];
167+
// Apply method with arrays
168+
book.apply(swiss, flightData);
169+
// Call method with arrays
170+
book.call(swiss, ...flightData);
171+
172+
// 🔸 The Bind Method 🔸
173+
// book.call(eurowings, 23, 'Sarah Williams');
174+
175+
const bookEW = book.bind(eurowings);
176+
const bookLH = book.bind(lufthansa);
177+
const bookLX = book.bind(swiss);
178+
bookEW(23, "Steven Williams");
179+
bookLH(100, "Bob Proctor");
180+
bookLX(342, "James Bond");
181+
182+
const bookEW23 = book.bind(eurowings, 23);
183+
bookEW23("Victor Eke");
184+
bookEW23("Paula Cole");
185+
186+
// Bind with Event Listeners
187+
lufthansa.planes = 300;
188+
lufthansa.buyPlane = function () {
189+
console.log(this);
190+
191+
this.planes++;
192+
console.log(this.planes);
193+
};
194+
// lufthansa.buyPlane();
195+
196+
document
197+
.querySelector(".buy")
198+
.addEventListener("click", lufthansa.buyPlane.bind(lufthansa));
199+
200+
// Partial Application
201+
const addTax = (rate, value) => value + value * rate;
202+
console.log(addTax(0.1, 200));
203+
204+
const addVAT = addTax.bind(null, 0.23);
205+
// addTax = value => value + value * 0.23;
206+
207+
console.log(addVAT(100));
208+
console.log(addVAT(23));
209+
210+
// Practice Exercise
211+
const addTaxRate = function (rate) {
212+
return function (value) {
213+
return value + value * rate;
214+
};
215+
};
216+
217+
const addVat2 = addTaxRate(0.23);
218+
console.log(addVat2(100));
219+
console.log(addVat2(23));

0 commit comments

Comments
 (0)