Interview Question
Share Lesson

Fix 'this'

Loading...

You are building a web application in JavaScript to host meetings. You are on a tight deadline, so you immediately head to StackOverflow to copy-paste some code to get started.

You try it out in the JS console in your browser, but it doesn't work. The getPresenterName and printSeatNumber calls are both broken. The getPresenterName should return the name of the first person in the users array, and printSeatNumber should console.log their index in the users array.

You should only make changes to the Meeting class. Fix these two issues by using the minimal amount of refactoring required, and don't add any new properties or methods to either class.

Each function has its own independent bug, so you should fix them separately.

 

This question is a bit open-ended because there are many ways to fix or refactor a problem. This also isn't a data structure and algorithm question, so we can't use Big O complexity as our guiding metric. Instead, we're told to fix the bugs in each case by performing as little refactoring as possible and by only changing Meeting.

Once we have the code debugged, the actual output should be:

 

To solve our problem, we will focus on each issue separately.

getPresenterName()

We set the getPresenterName function in the contructor of Meeting. At first glance, it seems pretty straightforward. We consider the first user to be the presenter, so we assign their getName method to getPresenterName. However, when we call it, we receive undefined when we're expecting it to be "Jeni".

To begin debugging, we console.log(presenter) which does match the "Jeni" User. Let's now console.log(this) inside getName. When we do, we realize that this is pointing to Meeting even though we originally define this.name on the User.

With JavaScript, the context of this is set based on where a function is called and not where it is defined. When we assign this.getPresenterName = presenter.getName;, we are changing the object that calls the method. To fix this bug, we need to bind getName with the presenter.

 

printSeatNumber()

When we try to print the seat for any user, it logs 3 every time. This is interesting because the index 3 is larger than our input array, and it is duplicated for each user even though we use their index in each loop iteration.

It appears that it is using the value of i after the loop ends - i < array.length is 3 < 3 which is false and the terminating condition.

We declared our variable var i = 0, and this makes it function scoped. Since printSeatNumber is a callback, it has formed a closure around i and the value is owned by the outer function scope. What happens is that the declaration of var i is hoisted outside the for loop to the top of the function and its value persists inside the entire scope. This means when printSeatNumber is executed, it uses the value that persisted in i which we ultimately incremented to 3.

 

One way to fix this would be to create a new scope inside our callback. We can create an IIFE (immediately invoked function expression) where we pass the index as a parameter, and then our callback will use this new value.

 

There's an even more concise way to handle it though. In ES2015, there were two new ways to declare variables, let and const. These values are block scoped instead of function scoped. This means if we declare let i = 0, its value will only live inside a given iteration and will be what the callback has access to.

 

Solution

This problem contained two very common issues in JavaScript. The first is using the correct this context since it changed based on where the method was called, which we solved by calling bind with the correct object. The other issue was a bug with our scope which we fixed by changing var to let so that the array index was retained within block scope instead of being controlled in the function scope of setUserSeats.

The complete changes we make to Meeting to fix our code:

 
Ready for the next step?
Find a Job
Loading...
Follow teacher
Share:

Table of Contents