Variables in JavaScript are lexically scoped. But, I wonder, is the this keyword, referring to the receiver of a method, an example of dynamic scoping. Or is this unrelated to the lexical/dynamic scoping discussion?

var foo = { x = “how am I scoped?” }
function bar() {
    console.log(this.x) // the free variable this is decided by the calling context, like I see dynamic scoping described
  • 3
    this is more like an invisible function argument. It is not an example of dynamic scoping. Languages that feature dynamic scoping include shell/Bash and Perl via the local keyword, and a huge amount of template languages.
    – amon
    Aug 18 '19 at 6:57

Dynamic scope seems to imply, and for good reason, that there's a model whereby scope can be determined dynamically at runtime, rather than statically at author-time. That is in fact the case.

Let's illustrate via code:

function foo() {
    console.log( a ); // 2

function bar() {
    var a = 3;

var a = 2;


Lexical scope holds that the RHS reference to a in foo() will be resolved to the global variable a, which will result in value 2 being output.

Dynamic scope, by contrast, doesn't concern itself with how and where functions and scopes are declared, but rather where they are called from. In other words, the scope chain is based on the call-stack, not the nesting of scopes in code.

So, if JavaScript had dynamic scope, when foo() is executed, theoretically the code below would instead result in 3 as the output.

function foo() {
    console.log( a ); // 3  (not 2!)

function bar() {
    var a = 3;

var a = 2;


How can this be? Because when foo() cannot resolve the variable reference for a, instead of stepping up the nested (lexical) scope chain, it walks up the call-stack, to find where foo() was called from. Since foo() was called from bar(), it checks the variables in scope for bar(), and finds an a there with value 3.

Strange? You're probably thinking so, at the moment.

But that's just because you've probably only ever worked on (or at least deeply considered) code which is lexically scoped. So dynamic scoping seems foreign. If you had only ever written code in a dynamically scoped language, it would seem natural, and lexical scope would be the odd-ball.

To be clear, JavaScript does not, in fact, have dynamic scope. It has lexical scope. Plain and simple. But the this mechanism is kind of like dynamic scope.

The key contrast: lexical scope is write-time, whereas dynamic scope (and this!) are runtime. Lexical scope cares where a function was declared, but dynamic scope cares where a function was called from.

Finally: this cares how a function was called, which shows how closely related the this mechanism is to the idea of dynamic scoping.

Source: You Don't Know JS: Scope & Closures

  • 2
    This is confusing values and variables. this cares cares how a function is called the same way parameters care how a function is called - they get their value at runtime when the function is called. But the scope of all variables (including this) is lexical and not dynamic.
    – JacquesB
    Aug 22 '19 at 6:55
  • Clear explanation! (The link is broken)
    – AliN11
    Apr 11 at 11:49

No, this is lexically scoped to a function, just like a function parameter. It basically works like an implicit parameter.

Dynamic scoping means that if a variable is defined in a function, it is also visible inside functions called from this function (and functions called from those functions and so on).

This is not what happens with this though. Each function invocation have its own this binding which is set at the time of the function invocation (just like regular parameter values are set at the function invocation). The this of the calling function is not visible for the called function, so there is no dynamic scoping. (When a function is called without dot-notation, this is just set to global or undefined.)

A useful way of thinking of this is as a hidden parameter, like this:

Actual syntax:           What happens conceptually:

function bar() { }  ->   function bar(this) {}
foo.bar();          ->   bar(foo);             
bar();              ->   bar(undefined);  

So this is basically a syntactic trick to pass the stuff left of the dot as a parameter. But it doesn't affect scoping, and isn't anymore "dynamic" or "runtime" than regular parameters.

And just to dispel any doubt - the ECMAScript spec is clear that this is lexically scoped:

8.3.2 GetThisEnvironment ( )

The abstract operation GetThisEnvironment finds the Environment Record that currently supplies the binding of the keyword this. GetThisEnvironment performs the following steps:

  1. Let lex be the running execution context’s LexicalEnvironment.
  2. Repeat

    • a. Let envRec be lex’s EnvironmentRecord.
    • b. Let exists be envRec.HasThisBinding().
    • c. If exists is true, return envRec.
    • d. Let outer be the value of lex’s outer environment reference.
    • e. Let lex be outer.

NOTE The loop in step 2 will always terminate because the list of environments always ends with the global environment which has a this binding.

Source: http://www.ecma-international.org/ecma-262/6.0/#sec-getthisenvironment

  • I think adding an example on what happens with const b = foo.bar; b(); would be useful
    – gcali
    Aug 22 '19 at 17:02
  • @gcali: Callig b() is equivalent to calling bar() in the example. It doesn't matter that the function is also attached to an object, it only matters if it is called using "dot" notation or not.
    – JacquesB
    Mar 31 '20 at 8:43
  • Sure, that's the reason I'm saying that adding the example would be useful; I think it could help clarify the subject. Something like const b = foo.bar; b(); -> bar(undefined);. Just my two cents!
    – gcali
    May 28 '20 at 7:16
  • @JacquesB Maybe .call() and .apply() worth mentions for "dot-like" behaviour? and .bind() as "currying" this approach? Nov 25 '20 at 10:51

Not the answer you're looking for? Browse other questions tagged or ask your own question.