DEV Community

Matt Zuckermann
Matt Zuckermann

Posted on

Learning how to use JavaScript 'this' keyword

Why I decided to blog about "this":

I'm a big fan of the Syntax.fm podcast by Wes Bos and Scott Tolinski, and I remember hearing an episode where Wes said something to the point of a developer really needing to build a site around the JavaScript this keyword due to the mysterious output we developers so often get when attempting to use it in various contexts.

Of course, there is a plethora of documentation on the topic already, and I don't intend to outshine any of that (I do love the MDN Web Docs). Rather, this blog series along with my site usethis.dev will hopefully be able to accomplish centralizing articles and documentation, as well as provide opportunities for developers to quiz themselves on content discussed.

So without any further introduction, let's get started!

What we'll be learning in this series:

We'll be learning the basics of the JavaScript this keyword in various contexts, the use of bind, the window object, block and function scope, and the difference between regular functions and arrow functions (and, in turn, the effects they have on the this keyword).

Alt Text

What we'll be learning in this post:

Today, we will be discussing the global window object, block and function scope, JavaScript data types, and gaining a general understanding of what this will output in a given environment.


This in Action

As a brief overview, here is a succinct statement on the topic of this from the MDN Web Docs:

In most cases, the value of this is determined by how a function is called (runtime binding).

-- MDN

While it may seem deceivingly simple, the this keyword is not like other keywords in JavaScript. It is completely determined on where it is called. For example, in the code below, we have used this not in a function, but simply within a bare HTML script tag.

<script>
  console.log(this) // Window { window: Window, self: Window, document, name: "..."} etc.
</script>
Enter fullscreen mode Exit fullscreen mode

You can also get the same result by opening up the developer tools in any browser, go to the console tab, and enter this as shown below in Chrome:

Alt Text

The reasoning behind the following output is that there is no other object (remember this key term for later) encapsulating the this keyword from which it will assume that environment. Only the window object is encapsulating the this keyword.

To further explain this, let's look at a couple other examples:

Examples

// Example 1
const wrapperFunction = function () {
  console.log(this)
}

// Example 2
const wrapperObjectWithFunction = {
  key: function () {
    console.log(this)
  },
}
Enter fullscreen mode Exit fullscreen mode

What do you think these will output? Take a moment before scrolling down to view the answer.

What

Are

The

Answers

Going

To

Be

Here?

Results

// Example 1
const wrapperFunction = function () {
  console.log(this) // Window { window: Window, self: Window, document, name: "..."} etc.
}

// Example 2
const wrapperObject = {
  log: function () {
    console.log(this) // {log: ƒ}
  },
}
Enter fullscreen mode Exit fullscreen mode

You might be surprised to see that in our first example, what is logged out is once again the window object. Now, why is that?

We must first understand that JavaScript variables can contain expressions. A simple yet pointless expression could be

const sum = 1 + 1 // 2
Enter fullscreen mode Exit fullscreen mode

A common misconception in metaphor that many programmers have is thinking of variables as a box "holding" a value (i.e. sum holding the value of 2).

Instead, variables act rather as pointers. Variables point to either primitives (i.e. string, number, boolean, bigint, symbol, undefined, or null), functions, or objects. (If you'd like to go deeper in this topic rather than get a 10,000 foot view, you should definitely check Dan Abramov's course Just JavaScript)

Thus, when we are logging this within a function we are not in fact logging out the variables assigned the function. That would be a bit of an oxymoron since the variable is the evaluation of an expression. Put simply, a function is really just a group of expressions to perform a particular task. Thus, it would make sense that we get the window object in the first example since the variable is defined within the global scope.

Remember what we said about variables being pointers to either primitives, functions, or objects? Well, the same attribute stands for object keys. In the second example, the log key is pointing to the function with the console.log method. The only difference is objects create their own block scope which changes the value of this. In this instance, the function is being pointed to by the log key which is defined within the object pointed to by the objectWrapper variable. As a result, the function is not bound to the global window object but instead it is tied locally to the object it is defined, which is why we are logging out an object containing the key {log: f}

In our next article, we will be looking further at the difference the this keyword has within arrow functions as well as the implications block scope has with different variables.

Discussion (0)