HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptCritical

How does the "this" keyword work, and when should it be used?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
howshouldandusedthedoeswhenthiskeywordwork

Problem

I am looking to find a clear explanation of what the "this" keyword does, and how to use it correctly.

It seems to behave strangely, and I don't fully understand why.

How does this work and when should it be used?

Solution

this is a keyword in JavaScript that is a property of an execution context. Its main use is in functions and constructors.
The rules for this are quite simple (if you stick to best practices).
Technical description of this in the specification

The ECMAScript standard defines this via the abstract operation (abbreviated AO) ResolveThisBinding:

The [AO] ResolveThisBinding […] determines the binding of the keyword this using the LexicalEnvironment of the running execution context. [Steps]:

  • Let envRec be GetThisEnvironment().



  • Return ? envRec.GetThisBinding().



Global Environment Records, module Environment Records, and function Environment Records each have their own GetThisBinding method.

The GetThisEnvironment AO finds the current running execution context’s LexicalEnvironment and finds the closest ascendant Environment Record (by iteratively accessing their [[OuterEnv]] properties) which has a this binding (i.e. HasThisBinding returns true). This process ends in one of the three Environment Record types.

The value of this often depends on whether code is in strict mode.

The return value of GetThisBinding reflects the value of this of the current execution context, so whenever a new execution context is established, this resolves to a distinct value. This can also happen when the current execution context is modified. The following subsections list the five cases where this can happen.

You can put the code samples in the AST explorer to follow along with specification details.
  1. Global execution context in scripts



This is script code evaluated at the top level, e.g. directly inside a `:

// Global context
console.log(this); // Logs global object.

setTimeout(function(){
console.log("Not global context");
});



When in the initial global execution context of a script, evaluating
this causes GetThisBinding to take the following steps:

The GetThisBinding concrete method of a global Environment Record envRec […] [does this]:

  • Return envRec.[[GlobalThisValue]].



The [[GlobalThisValue]] property of a global Environment Record is always set to the host-defined global object, which is reachable via
globalThis (window on Web, global on Node.js; Docs on MDN). Follow the steps of InitializeHostDefinedRealm to learn how the [[GlobalThisValue]] property comes to be.
  1. Global execution context in modules



Modules have been introduced in ECMAScript 2015.

This applies to modules, e.g. when directly inside a
, as opposed to a simple .

When in the initial global execution context of a module, evaluating
this causes GetThisBinding to take the following steps:

The GetThisBinding concrete method of a module Environment Record […] [does this]:

  • Return undefined.



In modules, the value of
this is always undefined in the global context. Modules are implicitly in strict mode.
  1. Entering eval code



There are two kinds of
eval calls: direct and indirect. This distinction exists since the ECMAScript 5th edition.

  • A direct eval call usually looks like eval(); or (eval)(); (or ((eval))();, etc.).1 It’s only direct if the call expression fits a narrow pattern.2



  • An indirect eval call involves calling the function reference eval in any other way. It could be eval?.(), (, eval)(), window.eval(), eval.call(,), etc. Given const aliasEval1 = eval; window.aliasEval2 = eval;, it would also be aliasEval1(), aliasEval2(). Separately, given const originalEval = eval; window.eval = (x) => originalEval(x);, calling eval() would also be indirect.



See chuckj’s answer to “(1, eval)('this') vs eval('this') in JavaScript?” and Dmitry Soshnikov’s ECMA-262-5 in detail – Chapter 2: Strict Mode (archived) for when you might use an indirect
eval() call.

PerformEval executes the
eval code. It creates a new declarative Environment Record as its LexicalEnvironment, which is where GetThisEnvironment gets the this value from.

Then, if
this appears in eval code, the GetThisBinding method of the Environment Record found by GetThisEnvironment is called and its value returned.

And the created declarative Environment Record depends on whether the
eval call was direct or indirect:

  • In a direct eval, it will be based on the current running execution context’s LexicalEnvironment.



  • In an indirect eval, it will be based on the [[GlobalEnv]] property (a global Environment Record) of the Realm Record which executed the indirect eval.



Which means:

  • In a direct eval, the this value doesn’t change; it’s taken from the lexical scope that called eval.



  • In an indirect eval, the this value is the global object (globalThis).



What about
new Function? — new Function is similar to eval`, but it doesn’t call the code immediately; it creates a function. A this binding doesn’t apply anywhere here, except when the function is called, which works normally, as explained in the next subsection.
  1. Entering function code



En

Context

Stack Overflow Q#3127429, score: 1506

Revisions (0)

No revisions yet.