Dynamic Scope VS Lexical Scope in Javascript.

The dynamic behavior of this.


Allan Sendagi

2 years ago | 2 min read

Let's look at an example:

I have added a,b and c to the console.logs for clarity.

We have a variable a that is a function. Inside this function, we have another variable const b that is also a function that we run at the end — b(); Inside of b, we have another function c but this time around c is an object that has property hi which is a function. We are calling c.hi() at the end.

Let's find out what happens when we run this function.

Let’s go through what happened here.

With athis is the window object. This makes sense because to the left of the dot, or who called a is the window object.

With b, we see that its nested inside of but still to the left of the dot is still the window object. There is no other object except for the window object. Here is whats going on — window.a(b());

How about c?
c, we have an interesting case. Here we have an object which as we know should change something. So we have c.hi(). In this case, to the left of the dot is cc called hi. So this here is the c object.

And this should raise some questions in your head because as we have seen with lexical scope or lexical environment, the compiler knows without running any piece of code what variables functions have access to. Here it appears as though lexical scope doesn't work with this.

It doesn't really matter where we write it in a piece of code. All that matters is how it gets called — during invocation, who calls it. All that matters is how the function is called.

Let's look at another example:

Let's see what happens

We have a here, and the value of this is the obj. This makes sense.

But b doesn't make sense. It refers to the window object! But isn’t inside of the obj?

This is one of the biggest gotchas when it comes to the this keyword because it's not lexically scoped. It doesn't matter where it is written. What matters is how the function was called.

What happened is that obj.sing() ran and inside of the sing function is where anotherFunction ran. So obj didn't really call anotherFunction. The sing function did. In Javascript, this keyword defaults to the window object.

In Javascript, our lexical scope which is the (available data + variables where the function was defined ) determines our available variables. Not where the function is called(Dynamic scope).

However, there is a little footnote to this statement. Because everything in Javascript is lexically scoped, how you write it determines what we have available except for the this keyword. this is dynamically scoped. That is, it doesn't matter where it was written, what matters is how the function was called.

So how do we fix this problem?

We can solve this issue using Es6 arrow functions. You might have heard that arrow functions are lexically bound. Arrow functions have a lexical behavior unlike normal functions.

So if we change our function, we see that it lexically binds this.

Here the object surrounding this is the main object — obj. The problem is solved.

But what did people do before arrow functions? They used bind.

obj.sing () returns a function but if we call it again, we get this to refer to the obj.

And there is another way of solving this issue.

What we would do is outside the function itself, we would create a reference so that var self = this.

And because at a time this line is run, this is still inside of the obj, we are going to maintain the reference to that object.

Here we can use self inside of anotherFunction, so that when we run the function, we see that both the sing function have a reference to the object using the self variable.


Created by

Allan Sendagi

Technology will save homo sapiens from extinction







Related Articles