Execution context

The this keyword is usually determined at the calltime of the function and will normally resolve to the object that the function is being invoked on. It is sometimes referred to as the execution context of a function or its thisArg. This can be unintuitive since it means that the this value can technically change between calls. For example, we could assign a method from one object to another, call it on the second, and observe that its this is always the object it's been called on:

const london = { name: 'London' };
const tokyo = { name: 'Tokyo' };

function sayMyName() {
console.log(`My name is ${this.name}`);
}

sayMyName(); // => Logs: "My name is undefined"

london.sayMyName = sayMyName;
london.sayMyName(); // => Logs "My name is London"

tokyo.sayMyName = sayMyName;
tokyo.sayMyName(); // => Logs "My name is Tokyo"

When called without an object of invocation, as is the case when we directly call sayMyName, its presumed execution context is the global environment in which the code resides. On the browser, this global environment is equal to the window object (which provides access to the browser-and-document object models), while in Node.js, this refers to an environment that's unique to each specific module/file, which includes, among other things, that module's exports.

In addition to the case of calling a function globally, there are two cases where the this keyword will be something other than the apparent object of invocation:

  • If the function being called was defined as an arrow-function, then it will absorb the this value from the scope in which it is situated
  • If the function being called is a constructor, its this value that will be a new object that has its [[Prototype]] preset to the prototype property of the function

There are also ways to force the value of this when calling or declaring a function. You can use bind(X) to create a new function that will have its this value set to X:

const sayHelloToTokyo = sayMyName.bind(tokyo);
sayHelloToTokyo(); // => Logs "My name is Tokyo"

You can also use a function's call and apply methods to force the this value for any given invocation, but note that this will not work if the function is being called as a constructor (that is, with a new keyword) or if it has been defined with the arrow-function syntax:

// Forcing the value of `this` via `.call()`:
tokyo.sayMyName.call(london); // => Logs "My name is London"

In your everyday function calls, it's best to avoid awkward techniques of invocation like this. Such techniques can make it difficult for the readers of your code to discern what's happening. There are many valid applications of invoking via callapply, or bind, but these are usually limited to lower-level libraries or utility code. Higher-level logic should avoid them. If you find yourself having to rely on these methods in higher-level abstractions, then you're likely making something more complicated than it needs to be. 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset