Object-Oriented JavaScript — Closures
Tags: webdev, programming, javascript, beginners
Published: 2021-01-24 21:52:25

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at functions.

### Functions that Return Functions

Fnctions can return functions.

For instance, we can write:

```
function a() {
  console.log('foo');
  return function() {
    console.log('bar');
  };
}
```

We return a function and then we can call the function we return.

For instance, we can write:

```
a()();
```

Then first call `a` , so `'foo'` is logged.

Then we call the returned function with the second parentheses, so we get `'bar'` logged.

### Functions that Rewrites Itself

We should be aware that functions can rewrite themselves.

For instance, we can write:

```
function a() {
  console.log('foo');
  a = function() {
    console.log('bar');
  };
}
```

Then we get `'foo'` logged.

The first console log runs, then the function is reassigned.

We shouldn’t do that and linters will alert us if we do this.

### Closures

Closures are functions that have other functions inside it.

The inner functions can access the outer function’s scope.

For instance, if we have:

```
function outer() {
  let outerLocal = 2;

  function inner() {
    let innerLocal = 3;
    return outerLocal + innerLocal;
  }
  return inner();
}
```

We have the `inner` function with the `innerLocal` variable.

This is only available within the `inner` function.

It can also access the `outer` function’s `outerLocal` variable.

This is useful because we want to have private variables in our code.

We have `outerLocal` and `innerLocal` that are only available `inner` .

`outer` can’t access the variables of `inner` .

So we have different levels of privacy with these functions.

### Closures in a Loop

If we have a loop that looks like:

```
function foo() {
  var arr = [],
    i;
  for (i = 0; i < 3; i++) {
    arr[i] = () => i
  }
  return arr;
}
```

Then if we call it:

```
const arr = foo();
for (const a of arr){
 console.log(a());
}
```

then we get 3 from all the console logs.

This is because `i` is 3 when we assigned the added our function to `arr` .

`var` isn’t block-scoped, so we would get the last value of `i` instead of what’s in the loop.

To get the value of `i` from the loop heading to the function we assign, we write:

```
function foo() {
  var arr = [],
    i;
  for (i = 0; i < 3; i++) {
    ((j) => {
      arr[i] = () => j
    })(i)
  }
  return arr;
}
```

Then we get 0, 1, and 2 as we expect.

We can also replace `var` with `let` to make `i` block-scoped and avoid this issue.

### Getter and Setter

Getter functions return values and setters sets values.

We can put the getter and setter functions into a closure so that we can keep them private.

For instance, we can write:

```
let getValue, setValue;
(() => {
  let secretVal = 0;
  getValue = () => {
    return secretVal;
  };

  setValue = (v) => {
    if (typeof v === "number") {
      secretVal = v;
    }
  };
}());
```

And we run a function to assign the `getValue` and `setValue` functions with functions.

`getValue` returns the value of `secretVal` and `setValue` sets it.

This way, we keep `secretVal` secret.

### Conclusion

Closures are great for various applications.

It’s mostly to keep variables private, and we can also use them to bind variables values the way we expect.