526305 (9) [Avatar] Offline
#1
in Listing 10.09 (https://jsbin.com/mibube/edit?js,console) you use this bit of code:

keys.forEach(function (key) {
console.log(key + " goes to " + exits[key].title);
});

in the showExits function. But if we copy that over to the showExits method in Listing 10.10


Object.keys(this.exits).forEach(function (key) {
console.log(key + " goes to " + this.exits.title);
});


(https://jsbin.com/hafusas/edit?js,console)


we get a TypeError: Cannot read property 'title' of undefined.



We can fix it in two ways:



var exit = this.exits;

Object.keys(this.exits).forEach(function (key) {
console.log(key + " goes to " + exit.title);
});


(https://jsbin.com/zunizom/edit?js,console)


or even using an fat-arrow function:



Object.keys(this.exits).forEach( key => {
console.log(key + " goes to " + this.exits[key].title);
});



(https://jsbin.com/fijoxeh/edit?js,console)





I was wondering if you might be able take a moment and explain why the first is broken, and why the second two are not broken. I suppose what I am asking is: how does "this" work in these three examples?


Thanks!
M.

John Larsen (68) [Avatar] Offline
#2
When you call kitchen.showExits(), your kitchen object acts as the context for the showExits function. The code immediately inside the showExits function can then use this to point to that kitchen object. So this.exits is essentially kitchen.exits.

However, If you create a new function using the function () {} notation, it will have its own context. In your example, you create an inline function and pass it to forEach. Because it is inline and not called as the method of an object, it uses the global object (in this case window) as its context. But window doesn't have an exits property - it is undefined - and undefined doesn't have any properties, including a title.

If you assign this to a variable within showExits but outside of the nested function, you are assigning kitchen to the variable (or whatever the context is). You can then use the variable in the nested function as it is in scope.

Fat arrow functions inherit the context from their scope. In your case this continues to point to kitchen.

I hope that helps. Let me know if you want it broken down any further.

John
526305 (9) [Avatar] Offline
#3
In your example, you create an inline function and pass it to forEach. Because it is inline and not called as the method of an object, it uses the global object (in this case window) as its context.


Ah ha! Thank you for the clarification!