What is "this"? Why you should avoid arrow functions on Vue methods
Tags: javascript, vue, webdev
Published: 2021-04-23 19:44:27

---
title: What is "this"? Why you should avoid arrow functions on Vue methods
published: true
tags: javascript, vue, webdev
cover_image: https://res.cloudinary.com/dzynqn10l/image/upload/v1619206915/JS%20Bits/what-is-this-cover_ee5muw.jpg
---

# `this` in Vue

Every Vue instance has an option for methods. This is simply an object whose properties are methods we'll use in our Vue app:

```js
const app = Vue.createApp({
  data() {
    return { count: 4 };
  },
  methods: {
    increment() {
      // "this" will refer to the component instance
      this.count++;
    }
  }
});
```
Vue will bind the `this` keyword to the instance so that it will always reference the component instance. Because of this, it's really import to not use arrow functions when defining methods because they always bind this to the parent context, which is not actually the Vue instance - but the global object (the Window):

```js
const app = Vue.createApp({
  data() {
    return { count: 4 };
  },
  methods: {
    increment: () => {
      // "this" will refer to the Window
      this.count++;
    }
  }
});
```

# Y Tho
The reason is that every **regular** (non-arrow) function defines its own `this` value, which **always refers to the owner of the function it's in**.

So in this example:
```js
const person = {
  name: 'Ted',
  logName() { 
    console.log(this.name); // Ted
    console.log(this); // person object
  }
};

person.logName();
```
`this` refers to the `person` object, which is `logName`'s owner.

This is true even when inside a stand alone function:

```js
function test() { console.log(this); }
test(); // Window is logged
```
That's because the owner of `test` is the window object:
```js
window.test; // test() { console.log('this', this); }
```
There's a huge exception to this. Whenever `this` is used **inside of a function within another method**, its binding is lost and `this` will then refer to the global (window) object:

```js
const obj = {
  func1() {
    console.log('func1 this', this); // "this" is obj
    (function func2() {
      // "this" binding is lost here
      console.log('func2 this', this); // "this" is Window
    })();
  }
};

obj.func1();
```
This is considered somewhat of a bug in the JavaScript language since it's very quirky and trips up a lot of people. 

When arrow functions were released in ES6 they provided a way to force `this` to automatically bind to the parent scope which produces a more expected outcome:

```js
const obj = {
  func1() {
    console.log('func1 this', this); // "this" is obj
    (() => {
      console.log('func2 this', this); // "this" is obj
      // "this" was bound to func1's "this" reference
    })();
  }
};

obj.func1();
```

The really important takeaway here is that **arrow functions do not have their own `this`**. When you use the `this` keyword inside an arrow function you're referring to the `this` of either a surrounding regular function/method or the global object if there is none.

Let's look at another example:
```js
const person = {
  firstName: 'Bob',
  getName() {
    console.log(this.firstName);
  }
};

person.getName();// Bob
```

`person.getName` is a regular old function. That means it has its own `this` reference - which we learned is the owner of the function - the `person` object.

So what happens when we make `getName` an arrow function?

```js
const person = {
  firstName: 'Bob',
  getName: () => {
    console.log(this.firstName);
  }
};

person.getName(); // undefined
```

`this.firstName` is `undefined` in this case. Why? Because the `getName` arrow function is binding the `this` keyword to the `this` of a surrounding regular function, which there is none - so the global object is what's bound to `this`. And `window.firstName` is of course `undefined`.

# Tying it back to Vue

With this in mind, let's look back at a Vue instance object:

```js
const app = Vue.createApp({
  data() {
    return {
      firstName: 'Bob'
    }
  },
  methods: {
    getName() {
      console.log(this.firstName); // Bob
    }
  },
  created() {
    this.getName();
  }
});
```
`this` is being used inside a regular function and not arrow functions which means `this` is bound to an owner object. If we were to make `getName` an arrow function it would mean `this` becomes the global object like we saw in our previous examples. 

It's important to note that when using regular functions, Vue does its own assignment of the `this` keyword to be the actual Vue instance - so the owner object is a little different than if we were using our own custom object. This under-the-hood mapping allows us to access data properties and methods like `this.otherMethod` and `this.lastName` which is convenient.

# One last thing
While you should not use arrow functions to define methods, it's fine to use them **inside** your methods as the `this` keyword will bind to the correct parent reference.

```js
const app = Vue.createApp({
  data() {
    return {
      checkmark: '✔',
      letters: ['a', 'b', 'c']
    }
  },
  methods: {
    processLetters() {

      // Using arrow functions inside processLetters is fine!
      const processedArray = this.letters.map(letter => {
        // "this" here binds to the "this" of processLetters
        return `${letter}-${this.checkmark}`
      });

      console.log(processedArray); // ["a-✔", "b-✔", "c-✔"]
    }
  },
  created() {
    this.processLetters();
  }
});
```

----------
Check out more #JSBits at my blog, [jsbits-yo.com](http://jsbits-yo.com/). Or follow me on [Twitter](https://twitter.com/JS_Bits_Bill)!