ES6 JavaScript— “this” keyword
By: Johnny Lai
Tags: Javascript Tips, Es6 Js, Es6 In Depth, Self Taught, Self Learning

Try to summarize the usage of “this” with examples

Every function created with the function keyword or with the method shorthand has its own “this”, and it generally binds to “who” called it.

Arrow functions don’t bind “this” to anything, the “this” inside depends on the surrounding context

Example 1

“handler” declared by error function here, that means the “this” is nothing, just same as outside the handler, thus the output is Window object

const handler = () => {

console.log(this);

};

btn1.addEventListener('click', handler);

Output

Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

Example 2

With “function” keyword here, the “this” binds to something. In this case, the browser automatically bind the “this” to button, because the button trigger the call

const handler = function() {

console.log(this);

};

btn.addEventListener('click', handler);

Output

<button id="btn1"></button>

Example 3

Why we need “this”

const name = 'Johnny';



const person = {

name: 'Fifi',

greet() {

console.log(name);

console.log(this.name);

}

};



person.greet();

Output

Johnny

Fifi

Example 4

As we called “newMovie.getFormattedTitle()”, the getFormattedTitle() binds to newMovie context. However, in the oldMovie, the getFormattedTitle() declared with arrow function, that means it bind to nothing instead of the surrounding context. In this case, the surrounding context is not inside oldMovie because we can’t place any “this” there, instead the surrounding context would be outside oldMovie. So we printed the Window object and unable to invoke oldMovie.getFormattedTitle();

That’s why we normally would not use arrow function inside object(In inner function, that is different case).

const newMovie = {

info: {

title:'007 No time to die'

},

getFormattedTitle() {

console.log (this.info.title.toUpperCase());

}

};

const oldMovie = {

info: {

title:'Saving private Ryan'

},

getFormattedTitle: ()=> {

console.log(this);

console.log(this.info.title.toUpperCase());

}

}; newMovie.getFormattedTitle();

oldMovie.getFormattedTitle();

Output

007 NO TIME TO DIE

Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

Uncaught TypeError: Cannot read property 'title' of undefined

Example 5

The this in Inner function of object is not bind to the object itself, instead it bind to Window

const newTeam = {teamName: 'ES6',

people: ['Johnny', 'Fifi'], getTeamMembers() {

this.people.forEach(p => {

console.log(p + ' - ' +this.teamName);

});

}}; const oldTeam = {teamName: 'Java',

people: ['Johnny', 'Fifi'], getTeamMembers() {

this.people.forEach(function(p) {

console.log(p + ' - ' + this.teamName);

});

}}; newTeam.getTeamMembers();

oldTeam.getTeamMembers();

Output

Johnny - ES6

Fifi - ES6

Window {parent: Window, opener: null, top: Window, length: 4, frames: Window, …}

Johnny - undefined

Window {parent: Window, opener: null, top: Window, length: 4, frames: Window, …}

Fifi - undefined

Example 6

It is always safe to use arrow function when declare function in class or invoke it in call back.

class Greeting { constructor() {

this.name = 'John';

} greetMorning() {console.log('Good Morning ' + this.name);} greetAfternoon = () => {console.log('Good Afternoon ' + this.name);};



greetEvening = function() {console.log('Good Evening ' + this.name);}

} const g = new Greeting(); g.name = "fifi" g.greetMorning();

g.greetAfternoon();

g.greetEvening(); const button1 = document.getElementById('btn1');

const button2 = document.getElementById('btn2');

const button3 = document.getElementById('btn3');

const button4 = document.getElementById('btn4');

const button5 = document.getElementById('btn5');

const button6 = document.getElementById('btn6'); button1.addEventListener('click', () => (g.greetMorning()));

button2.addEventListener('click', () => (g.greetAfternoon()));

button3.addEventListener('click', () => (g.greetEvening()));

button4.addEventListener('click', g.greetMorning);

button5.addEventListener('click', g.greetAfternoon);

button6.addEventListener('click', g.greetEvening);

Output