DEV Community 👩‍💻👨‍💻

delph
delph

Posted on

understanding 'this'

What is 'this'?

In short, this in JavaScript references the object that is executing the current function.

How then do we determine the object being referenced?

(#1.) If the function is part of an object (ie. a method), this references the object.

const bird = {
  name: "Tweety",
  printThis() {
    console.log(this); // `this` references `bird`
  }
};

bird.printThis(); // { name: 'Tweety', printThis: ƒ }

(#2.) If the function is a regular function (not part of an object), this references the global object in the running environment (ie. window in browsers and global in node)

function bird() {
  console.log(this);
}

// If called in browser:

bird(); // Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

Note: if a method has a callback function, this in the callback function references the global object.

const bird = {
  birdName: "tweety",
  sounds: ["chirp", "quack", "tweet"],
  printBirdSounds() {
    this.sounds.forEach(function(sound) {
      console.log(this.birdName, sound);
    });
  }
};

bird.printBirdSounds(); // undefined 'chirp'
// undefined 'quack'
// undefined 'tweet'

In the above example, this.sounds in the printBirdSounds() method correctly references the bird object as it follows rule 1 above.

However, as the line logging this.birdName is inside a regular function, this now follows rule 2 and references the global object. Since there is no birdName property on the global object, it prints undefined.

To fix this, see rule 4 below.

(#3.) If the function is called using the new keyword in the case of constructor functions, this references a new empty object.

function Bird() {
  console.log(this);
  this.name = "tweety";
  console.log(this);
}

new Bird();
// {}
// { name: 'tweety' }

(#4.) If this is used in an arrow function, the value of this is inherited from its enclosing scope (ie. follow lexical scoping rules).

This is because arrow functions do not have their own this value.

Rewriting the second example in rule 2 using arrow functions,

const bird = {
  birdName: "tweety",
  sounds: ["chirp", "quack", "tweet"],
  printBirdSounds() {
    this.sounds.forEach(sound => console.log(this.birdName, sound));
  }
};

bird.printBirdSounds(); // tweety 'chirp'
// tweety 'quack'
// tweety 'tweet'

With arrow functions, the line logging this.birdName now follows rule 1 and references the bird object!

(#5.) If bind, call, apply are used to call a function, this inside the function is the object that is passed in as the argument.

function bird() {
  console.log(this);
}

const tweety = {
  sound: "tweet"
};

const bindTweety = bird.bind(tweety);
bindTweety(); // { sound: 'tweet' }
bird.call(tweety); // { sound: 'tweet' }
bird.apply(tweety); // { sound: 'tweet' }

Top comments (2)

Collapse
 
danissss profile image
Gerardo

Thanks, finally I understand the use of "this" inside the arrow functions!! Good examples!!

Collapse
 
nlsanyu profile image
NLSanyu

This is very well explained. Thanks.

Timeless DEV post...

How to write a kickass README

Arguably the single most important piece of documentation for any open source project is the README. A good README not only informs people what the project does and who it is for but also how they use and contribute to it.

If you write a README without sufficient explanation of what your project does or how people can use it then it pretty much defeats the purpose of being open source as other developers are less likely to engage with or contribute towards it.