In order to understand this context within a function we must answer three questions:
- Was the function we're looking at invoked?
- How was it invoked?
- What's the context that it was invoked in?
The answer to question number three tells where the this keyword is coming from.
In the example below when we invoke getName() we get undefined is my first name
jsconst person = {firstName: 'tyler'}function getName() {return `${this.firstName} is my first name`}console.log(getName()) // undefined is my first name
Answering the questions above we can figure out what the issue is:
- Was the function we're looking at invoked?
- Yes - console.log(getName())
- How was it invoked?
- Implicitly bound with the open/close parenthesis
- What's the context that it was invoked in?
- getName() lives within the Window object
Having functions or variables living on the Window object is most likely always going to be where the issue exists. In this case the Window object does not have a firstName property on it, so it returns undefined.
To solve this issue we must explicitly bind the getName function and we can do it in a couple of different ways
Option 1: Use the call function prototype method and bind this context to another object.
jsconst person = {firstName: 'tyler'}function getName() {return `${this.firstName} is my first name`}console.log(getName.call(person)) // tyler is my first name
Option 2: Use the apply method, same as call() except it takes an array of arguments and those are spread out into the calling function.
jsconst person = {firstName: 'tyler'}function getName() {return `${this.firstName} is my first name`}console.log(getName.apply(person, [something, else])) // tyler is my first name
Option 3: Use the bind method, it does not invoke the function like call and apply did but returns a new function that can be called anywhere
jsconst person = {firstName: 'tyler'}function getName() {return `${this.firstName} is my first name`}window.setInterval(getName.bind(person), 3000)