Search code examples
javascriptprivateprivate-membersiife

Using IIFEs in JS for protecting data by creating private variables


I have created a small program to print some message in the console when a button in the DOM is clicked.

Code-

<!DOCTYPE html>
<html>
<body>
    <button onClick="printName()">Click</button>
</body>
<script>
    const personDetails = (function() {
        let name = 'john';
        function displayMsg() {
            console.log(name);
        }
        return {
            displayName: displayMsg
        }
    })();
    function printName() {
        personDetails.displayName(); 
    }
</script>
</html>

In above code, to protect name, I am using IIFE and returning a method displayName inside personDetails. On click of button, printName is executed which further executes personDetails.displayName. Here are my concerns -

  1. Is this the right way to use IIFEs to protect the data? If no, then please provide a solution. This is getting confusing everyday.
  2. Even if we are keeping only 1 global variables, other exposed variables are accessible through the global one like displayName method.
  3. Let's say I have successfully protected the data, still I am able to change the function definition in the console through personDetails.displayName which should be avoided.

    Old method: function displayMsg() { console.log(name); }
    New method: personDetails.displayName = function() { console.log('Hiiii'); }


Solution

  • Welcome to StackOverflow. Please take the tour and visit the help center.


    1. Is this the right way?

    There is at least one 'close' vote for this question being primarily opinion-based. That voter is correct that this portion of the question is hard to answer definitively.

    So let me just say that this is at least one appropriate way to do this. There are many others. You could simplify this, if you like, to

    const personDetails = (function() {
      let name = 'john';
      return {
        displayName: function() {
          console.log(name);
        }
      }
    })()
    

    And you could simplify it still more by using arrow functions.

    2. Why are other variables still exposed?

    That is the point of such code: to create a public interface that makes reference to some private data. You could also skip personDetails and expose only displayName by returning the function and not an object with that function as a property.

    But if you want to be able to use that data, then you need at least some public interface!

    3. How is it that this function reference can still be changed?

    There are techniques that would allow you to protect this variable from change. But then, perhaps, a user will redefine personDetails to be something else. Could you protect this? Maybe. But then what's to stop someone from intercepting your Javascript before it's interpreted by the browser, altering these definitions?

    The point is that you will only ever have so much control. If you don't trust users, you shouldn't be shipping them code... which means you shouldn't be writing for the web.

    Using IIFEs to protect data from accidental changes, or even well-meaning but dangerous intentional changes, is fine. Trying to pretend that you're entirely in charge of the code once it leaves your hands is folly however.