DEV Community

Cover image for Understanding closures in JavaScript
diego michel
diego michel

Posted on

Understanding closures in JavaScript

Closures are functions that have access to variables from another function's scope. This is often accomplished by creating a function inside a function.

function createComparisonFunction(propertyName) {         
 return function(object1, object2) {
  let value1 = object1[propertyName];
  let value2 = object2[propertyName];

  if (value1 < value2) {
   return -1;
  } else if (value1> value2) {
   return 1;
  } else {
   return 0;
  }
 };
}
Enter fullscreen mode Exit fullscreen mode

The highlighted lines in this example are part of the inner function (an anonymous function) that is accessing a variable (propertyName) from the outer function. Even after the inner function has been returned and is being used elsewhere, it has access to that variable. This occurs because the inner function's scope chain includes the scope of createComparisonFunction().

The activation object for the function is initialized with values for arguments and any named arguments. The outer function's activation object is the second object in the scope chain. This process continues for all containing functions until the scope chain terminates with the global execution context.

As the function executes, variables are looked up in the scope chain for the reading and writing of values.

function compare(value1, value2) {
 if (value1 < value2) {
  return -1;
 } else if (value1> value2) {
  return 1;
 } else {
  return 0;
 }
}

let result = compare(5, 10);
Enter fullscreen mode Exit fullscreen mode

This code defines a function named compare() that is called in the global execution context. When compare() is called for the first time, a new activation object is created that contains arguments, value1, and value2. The global execution context's variable object is next in the compare() execution context's scope chain, which contains this, result, and compare.

The this Object

Using the this object inside closures introduces some complex behaviors. When a function is not defined using the arrow syntax, the this object is bound at runtime based on the context in which a function is executed: when used inside global functions, this is equal to window in nonstrict mode and undefined in strict mode, whereas this is equal to the object when called as an object method.

Anonymous functions are not bound to an object in this context, meaning the this object points to window unless executing in strict mode. Because of the way closures are written, however, this fact is not always obvious.

window.identity = 'The Window';

let object = {
 identity: 'My Object',      
 getIdentityFunc() {
  return function() {
   return this.identity;
  };
 }
};

console.log(object.getIdentityFunc()()); // 'The Window'
Enter fullscreen mode Exit fullscreen mode

Remember that each function automatically gets two special variables as soon as the function is called: this and arguments. An inner function can never access these variables directly from an outer function. It is possible to allow a closure access to a different this object by storing it in another variable that the closure can access.

window.identity = 'The Window';

let object = {
 identity: 'My Object',      
 getIdentityFunc() {
  let that = this;
  return function() {
   return that.identity;
  };
 }
};

console.log(object.getIdentityFunc()()); // 'My Object'
Enter fullscreen mode Exit fullscreen mode

It's unlikely that you'll intentionally use the patterns in lines two or three, but it is helpful to know that the value of this can change in unexpected ways when syntax is changed slightly.

[this link for more information about closures]https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

support me for more content

Top comments (0)