THIS 2
| javascriptGonna explore where this
can go wrong by using a series of scenarios.
Scene 1: Passing a function that uses this
as a callback function
Imagine a view with a button. The button has an id of yoke and jQuery is being used.
var bizarre = {
subject: 'Yo mama',
joke: 'got an afro with a chin strap',
makeJoke: function() {
return this.subject + ' ' + this.joke;
}
};
var button = $('#yoke');
button.click(bizarre.makeJoke); // undefined
Soooooo I expected a joke, but got undefined
. In this scenario, the invoker is button
, so this
is set to the jQuery wrapped object. I’m certain this jQuery object does not have subject or joke properties…
One way of fixing the context of this
for this scenario is to use the bind()
method to hardcode the value of this
inside bizarre.makeJoke()
like so:
var bizarre = {
subject: 'Yo mama',
joke: 'got an afro with a chin strap',
makeJoke: function() {
return this.subject + ' ' + this.joke;
}
};
var button = $('#yoke');
button.click(bizarre.makeJoke.bind(bizarre)); // Yo mama got an afro with a chin strap
Scene 2: Using this
inside a closure
var momo = {
name: 'momo',
friends: [
{name: 'red', age: 17, favoriteColor: 'red'},
{name: 'erica', age: 17, favoriteColor: 'green'}
],
hasKnife: true,
callback: function() {
console.log(this.name); // momo
console.log(this.hasKnife); // true (oh shit)
this.friends.forEach(function(friend) {
console.log(this); // [object Window];
console.log('Friend of ' + this.name); // Friend of undefined
console.log(friend.name + ' is ' + friend.age + ' years old and likes ' + friend.favoriteColor);
// Red is 17 years old and likes red
// Erica is 17 years old and likes green
});
}
};
momo.callback();
What happened to Momo? Inside the forEach
method, an anonymous function was passed as the callback. This anonymous function cannot access its parent function’s this
. This issue can be addressed by saving the parent function’s this
to a local variable that is still accessible by the anonymous function.
var momo = {
name: 'momo',
friends: [
{name: 'red', age: 17, favoriteColor: 'red'},
{name: 'erica', age: 17, favoriteColor: 'green'}
],
hasKnife: true,
callback: function() {
console.log(this.name); // momo
console.log(this.hasKnife); // true (oh shit)
var self = this; // boom shakalaka
this.friends.forEach(function(friend) {
console.log(this); // [object Window];
console.log('Friend of ' + self.name); // Friend of momo
console.log(friend.name + ' is ' + friend.age + ' years old and likes ' + friend.favoriteColor);
// Red is 17 years old and likes red
// Erica is 17 years old and likes green
});
}
};
momo.callback();