# Bind, Call, and Apply Readme

In this code along, we will be practicing the use of `bind`, `call` and `apply`.

You can follow along using your browser's JS console, or use `httpserver` to serve the provided `index.html`. The HTML file will automatically load `index.js` and edits you make there will be shown in your browser.

## Objectives

1. Use `call()` and `apply()` to invoke a function with an explicit value for `this`
2. Explain the difference between `call()` and `apply()` in the way you pass arguments to the target function
3. Use `bind()` to create new functions that are associated to specified *contexts*
4. Use `bind()` to execute functions asynchronously

## Alternate Ways to Invoke Functions

In our exploration of `this`, we saw how it can change depending on how it is called. Let's take a look at a quick example. Copy and paste this into your browser's JS console to test for yourself:

```
function greet() {
	console.log(`my name is ${this.name}, hi!`);
}

greet(); // my name is , hi!

let person = {
	name: 'Bob',
	greet: greet
};

person.greet(); // my name is Bob, hi!
```

We have a function, `greet`, that logs a string. Interpolated into this string is `this.name`. When the `greet` is invoked as a function, `this` is referring to the [global object](https://developer.mozilla.org/en-US/docs/Glossary/Global_object), [window](https://developer.mozilla.org/en-US/docs/Web/API/Window). We say that the *context* for the `greet()` is `window`. In browser-based JavaScript, `window` is the "*default context*."

However, when `greet` is invoked as a method of *an object*, `this` changes to refer to the object the method is invoked in. That is, the *context* automatically changes to be the containing object. Since `person` has a `name` property set, `this.name` refers to the value 'bob'.

We've seen here that there are conditions where JavaScript will change the *context* ("what `this` is set to) automatically. Developers can also force functions to be executed in other contexts. Javascript allows us to do this using the `call` and `apply` methods.

```
function greet() {
	console.log(`my name is ${this.name}, hi!`);
}

let sally = { name: 'Sally' };

greet.call(sally);
// my name is Sally, hi!

greet.apply(sally);
// my name is Sally, hi!
```

As you see above, we can use `call` or `apply` to invoke a function with a specified *context*. The *context* in which the function is to be run is passed in as the first argument to these methods.

> **NOTE:** Our `greet` function is actually an instance of a `Function` class. Because of this a function instance *can also have methods*. Functions are things that run, but also things like `{}` in JavaScript.

Both `call` and `apply` let us set the value of `this` to whatever we pass as the first argument. The difference between the two is how arguments are passed to the function.

#### Passing Arguments With `call` and `apply`

Let's modify our `greet` function to be a little chattier:

```
function greet(customerOne, customerTwo) {
	console.log(`Hi ${customerOne} and ${customerTwo}, my name is ${this.name}!`);
}
```

Now, when we invoke `greet`, not only do we need to explicitly set `this`, but we also need to pass values for `customerOne` and `customerTwo`.

Using `call`, we pass the object for `this` as the first argument, followed by any function arguments in order.

```
let sally = { name: 'Sally' };

function greet(customerOne, customerTwo) {
	console.log(`Hi ${customerOne} and ${customerTwo}, my name is ${this.name}!`);
}

greet.call(sally, 'Terry', 'George');
// Hi Terry and George, my name is Sally!
```

Great! Now we see the name and the message! What happens if we don't pass any arguments?

```
greet.call(sally);
// Hi undefined and undefined, my name is Sally!
```

The call to `apply` works similarly to `call`, except that `apply` only takes two arguments: the value of `this`, and then an `Array` of arguments to pass to the function, like so:

```
greet.apply(sally, ['Terry', 'George']);
// Hi Terry and George, my name is Sally!
```

You can remember the difference because `apply` takes an **array** (both begin with the letter a). You can use either `call` or `apply`. The only difference is stylistic. Both exist because sometimes arguments need to be collected or bundled up (`apply`) versus passed directly (`call`).

### Introduce `bind`

So far, we have been looking at `call` and `apply`, which both explicitly set `this` and then immediately execute the function call.

Sometimes, we want to take a function, associate it to a *context* and return a "*context*-bound" version of the *original function*.

Once we have the "*context*-bound" version of the function we can call it with `(arguments, arguments, ...)` or `call()` or `apply()` without having to manually set the context. Let's see it in action.

```
let sally = { name: 'Sally' };

function greet(customer) {
	console.log(`Hi ${customer}, my name is ${this.name}!`);
}

let newGreet = greet.bind(sally); // newGreet is context-bound to sally

newGreet('Bob');
// Hi Bob, my name is Sally!

greet('Bob');
// Hi Bob, my name is !
```

As you see from the above code, by calling `greet.bind(sally)`, we return a new function that we then assign to the variable `newGreet`. Invoking `newGreet` shows that the `this` object is bound to `sally`.

Note that the original `greet` function is unchanged. `bind` does not change it. Instead, `bind` copies the function, and sets the copied function's `this` context to whatever is passed through as an argument.

We can actually use bind and invoke immediately:

```
greet.bind(sally)('Bob');
// Hi Bob, my name is Sally!
```

But this is just a noisy way of doing the same work of `call()` or `apply()`.

## bind(), call(), and apply() in JavaScript code

But assigning this to a variable like we did with `newGreet` makes this easily **reusable** and **transferable**. In complex applications, there are times when it is better that `this` refers to the context *we assign*. Until the introduction of [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this), every new JavaScript function defined its own `this` value. Using `bind`, we can prevent this behavior.

Let's imagine we want to create an app that matches user interests with keywords from upcoming events. We could create a `User` class and be able to assign properties to user instances, like a name and an array of interests. We can also include a class function, `matchInterests`, that takes in an event and returns true if there are any matching keywords:

```
class Event {
	constructor(title, keywords) {
		this.title = title;
		this.keywords = keywords;
	}
}

class User {
	constructor(name, interests) {
		this.name = name;
		this.interests = interests;
	}

	matchInterests(event) {
		return event.keywords.some(function(word) {
			return this.interests.includes(word);
		});
	}
}

let billy = new User('billy', ['music', 'art', 'movies']);
let freeMusic = new Event('Free Music Show', ['music', 'free', 'outside']);

billy.matchInterests(freeMusic);
// Uncaught TypeError: Cannot read property 'interests' of undefined
```

Here, a new `User` instance is created and assigned to `billy`. A name and interests are assigned as properties in the `constructor`. We've also created a new `Event`, with a title and keywords, assigned to `freeMusic`.

`matchInterests` is a class method that takes in an event object, checks to see if *some* event keywords are *included* in the user's interests, and returns true or false accordingly.

Except, when we call `billy.matchInterests(freeMusic);`, that is not what happens. The problem in our code above is here:

```
function(word) {
  return this.interests.includes(word);
}
```

Since every new function defines its own `this` value, when the callback function is invoked, `this` will be `undefined`. We can see this by logging inside and outside the function:

```
class Event {
	constructor(title, keywords) {
		this.title = title;
		this.keywords = keywords;
	}
}

class User {
	constructor(name, interests) {
		this.name = name;
		this.interests = interests;
	}

	matchInterests(event) {
		console.log("'this' is defined: ", this);
		return event.keywords.some(function(word) {
			console.log("'this' is now undefined: ", this);
			return this.interests.includes(word);
		});
	}
}

let billy = new User('billy', ['music', 'art', 'movies']);
let freeMusic = new Event('Free Music Show', ['music', 'free', 'outside']);

billy.matchInterests(freeMusic);
// 'this' is defined:  User {name: "billy", interests: Array(3)}
// 'this' is now undefined:  undefined
// Uncaught TypeError: Cannot read property 'interests' of undefined
```

In the first `console.log`, `this` refers to the `billy` user instance. In the second, `this` is `undefined`. To solve this problem, we can use `bind`:

```
class Event {
	constructor(title, keywords) {
		this.title = title;
		this.keywords = keywords;
	}
}

class User {
	constructor(name, interests) {
		this.name = name;
		this.interests = interests;
	}

	matchInterests(event) {
		return event.keywords.some(
			function(word) {
				return this.interests.includes(word);
			}.bind(this) // added to the and of the callback function
		);
	}
}

let billy = new User('billy', ['music', 'art', 'movies']);
let freeMusic = new Event('Free Music Show', ['music', 'free', 'outside']);

billy.matchInterests(freeMusic);
```

Let's see why the above code works. When the `matchInterests` method is invoked, `this` refers to the `User` instance context receiving the method call. We are in that context when our callback function is defined. Using `bind` here lets us keep `this` referring to the `User` context.

## A Brief Look at Arrow Functions

In modern JavaScript, arrow functions don't have their own `this`, so `this` will refer to whatever context the arrow function was invoked in. Using an arrow function, we could rewrite `matchInterests` as:

```
matchInterests(event) {
  return event.keywords.some(word => this.interests.includes(word));
}
```

Here, `this` will refer to the `User` instance context.

## Summary

We reviewed how `this` works for simple function calls. Then we saw how `call` and `apply` allow us to instantly execute functions while specifying the `this` value of the executed function. Then we learned how to use `bind` to make copies of functions with a new `this` value bound to the copy of the function.

## Resources

* [MDN: Function.prototype.call()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)
* [MDN: Function.prototype.apply()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
* [MDN: Function.prototype.bind()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)
* [No Separate This](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this)

Clone : <https://github.com/learn-co-curriculum/js-object-oriented-bind-call-apply-readme>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://certil-remy.gitbook.io/learn/javascript/oop/untitled-6.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
