Data encapsulation in JavaScript
Tags: javascript, beginners, reactnative, openai
Published: 2023-01-28 02:12:36


Data encapsulation and data privacy are crucial for programming. In JavaScript, **encapsulation** refers to the practice of hiding the internal state and implementation details of an object from the outside world, and providing a public interface for interacting with the object.

We need to defend our variables from being unintentionally overwritten by any part of the program, including external scripts and libraries. To achieve this, we must remember to hide variables and use scopes. 

PART I
Immediately Invoked Function Expressions [(IIFEs)](#iifes), [closures](#closures), and [blocks](#blocks) are all related to data encapsulation in JavaScript. 

PART II
[React](#react)'s state management promotes encapsulation, which is the idea of keeping data and functionality in one entity.

## IIFEs
 
IIFEs are functions defined and immediately executed, creating a private scope for variables inside the function, inaccessible from outside.

```jsx
(function () {
  var myData = 'This is some private data';
})();
console.log(myData);  // ReferenceError: myData is not defined

```

## Closures

Closures are similar to IIFEs in that they also create a new scope for variables, but they do so by returning a function that retains access to the variables in its scope. 

Here is an example of data encapsulation in JavaScript using closures:

```jsx
function createCounter() {
    let count = 0; // private variable

    return {
        increment: function() {
            count++;
        },
        decrement: function() {
            count--;
        },
        getCount: function() {
            return count;
        }
    };
}

let counter = createCounter();
console.log(counter.getCount()); // 0
counter.increment();
console.log(counter.getCount()); // 1
counter.decrement();
console.log(counter.getCount()); // 0
```
In the above code, the `createCounter` function returns an object with three methods: `increment`, `decrement`, and `getCount`. The `count` variable is declared inside the `createCounter` function, so it is only accessible within the scope of that function. The object that is returned by the `createCounter` function has access to the `count` variable through closure, but it is not directly accessible from outside the function. This is an example of data encapsulation, as the internal state of the object (the `count` variable) is hidden from the outside world, and can only be modified through the provided public methods (`increment`, `decrement`).

Closures are useful for creating functions that maintain state or pass data to a callback without making it globally accessible. If this is unclear, you may find my post [Clarity on closures in JavaScript](https://dev.to/bolouie/clarity-on-closures-in-javascript-4pmg) helpful.

Nowadays, JavaScript has made it so that IIFEs are not as necessary as they once were. If we need to create a new scope for data privacy, we can simply create a block instead - no need to create a function.

## Blocks

JavaScript blocks are also used to encapsulate data, by creating a new scope for variables defined within the block. 

Using `let` and `const` keywords allow you to declare variables with block scope, rather than function scope. This means you can create a new scope within a block of code, such as a `for` loop or an `if` statement, rather than having to wrap the code in an IIFE.

Here is an example of how you can use a block to achieve data encapsulation, instead of using an IIFE:

```jsx
{
    let count = 0; // private variable

    function increment() {
        count++;
    }
    function decrement() {
        count--;
    }
    function getCount() {
        return count;
    }
    console.log(count); // 0
    increment();
    console.log(count); // 1
    decrement();
    console.log(count); // 0
}
console.log(count); // ReferenceError: count is not defined
```

In the above code, the variable `count` is declared within a block, and it's only accessible within that block, making it private. Once the block ends, the variable is not accessible anymore, so trying to access it outside the block will raise a `ReferenceError`.

Though not essential as before, IIFEs may be useful in creating a new scope to prevent naming clashes or to maintain a certain state.

Use closures to create private variables and methods and encapsulate data to promote modularity and maintainability while controlling access. 

Closures enable code to maintain state and context, by allowing inner functions to access variables from the outer function even after the outer function has finished running. This is useful for tasks such as event handling, async programming, and data encapsulation.

## React

State management is a key concept in React and other JavaScript libraries and frameworks for building user interfaces. In React, **state** refers to the data or variables that determine a component's behavior and render information to the user.

React provides a way to manage state and props (a component's input) through a component's `state` object and the `setState` method. The `state` object contains the data that the component needs to render, and the `setState` method is used to update the state and trigger a re-render of the component. This allows the component to respond to user interactions, network responses, or other events and update the user interface accordingly.

React ensures components render consistently and re-render when state changes by storing it within the component and using `setState()`. It also allows for state to be managed in a functional way with hooks, which is less verbose and easier to understand than class-based components.

React promotes encapsulation with its state management, hiding internal state from outside and only allowing access through methods like `setState`, which makes components more predictable and prevents side effects.

Thanks for reading! This was produced with the help of artificial intelligence.