-1

I am having a problem grasping how to make javascript functions/variables private. How would I need to edit this to make the functions/variables private in something like this.

<html>
<head>
<style>
#panel, .flip {
  font-size: 16px;
  padding: 10px;
  text-align: center;
  background-color: #4CAF50;
  color: white;
  border: solid 1px #a6d8a8;
  margin: auto;
}

#panel {
  display: none;
}
</style>
</head>
<body>

<p class="flip" onclick="myFunction()">Click to show panel</p>

<div id="panel">
  <p>This panel contains a div element, which is hidden by default (display: none).</p>
  <p>It is styled with CSS and we use JavaScript to show it (display: block).</p>
  <p>How it works: Notice that the p element with class="flip" has an onclick attribute attached to it. When the user clicks on the p element, a function called myFunction() is executed, which changes the style of the div with id="panel" from display:none (hidden) to display:block (visible).</p>
  <p>You will learn more about JavaScript in our JavaScript Tutorial.</p>
</div>

<script>
function myFunction() {
  document.getElementById("panel").style.display = "block";
}
</script>

</body>
</html>
  • You do realize that when you make your `myFunction` private `onclick="myFunction()"` will not work any more? – 3limin4t0r Mar 17 '20 at 22:04
  • OK, I was given a task to create panel using css to hide it and Javascript to display it. I am to use private functions and variables. This is how I would normally accomplish the task, minus the private functions a variables, so I am at a loss as to how to accomplish this. All online resources don't seem to help. Thanks. – user1171786 Mar 17 '20 at 22:11
  • @user1171786 Who said you have to use "private" variables? If this is a school/class assignment then point out to your instructor/professor/lecturer/TA that there is no "private" functionality in JavaScript and ask them for clarification. – Dai Mar 17 '20 at 22:13

2 Answers2

2

You can't.

JavaScript doesn't have any notion of access modifiers (beyond export in a module, but <script> elements with inline scripts are not JavaScript modules).

Additionally, the private modifier in OOP languages only makes sense for class/struct types, not free-functions (as all free functions are globally scoped), so the idea of private function myFunction() { ... } is meaningless.

Presently in the JavaScript ecosystem, when working with a JavaScript class (which is just syntactic sugar for a prototype declaration) it's commonplace to denote "private" properties (including functions) by using a leading underscore - but this is a convention and not a language feature, nor does it prevent a function from being called from another script:

class Foobar {

    doSomething() { // <-- "public"
        // ...
    }

    _doSomethingElse() { // <-- the leading underscore is a hint to consumers not to use this property directly, but they can still call it if they want to.
        // ...
    }
}

var f = new Foobar();
f.doSomething();
f._doSomethingElse(); // <-- nothing stops a consumer from calling this function-property.

Workaround:

Note that you can have a JavaScript object (using a class or just a POJO) with inaccessible anonymous functions provided that you can wire them up in a way that doesn't expose them - but the downside to this approach is that your own code can't directly invoke them either. This approach can be used to set-up event handlers without polluting the global namespace:

class Foobar {

    constructor() {

        (function() { // This is an IIFE

            const button = document.getElementById( 'foobar' );
            button.addEventListener( 'click', function() {
                alert("clicked!);
            } );

        })();
    }

}



In the above code, the IIFE and the click event-handler functions now cannot be invoked directly because they don't have a name and after the script runs they won't be in-scope.

Dai
  • 141,631
  • 28
  • 261
  • 374
  • As an aside, this will likely change sometime soon! I hear `private` is coming down the tc39 pipeline, but additionally we may be getting `Realms` which will provide separate global contexts( think like an iFrame without the xhr ) with their own siloed prototypes, symbols and scope. Should be really interesting! – zfrisch Mar 17 '20 at 22:10
  • OK, I was given a task to create panel using css to hide it and Javascript to display it. I am to use private functions and variables. This is how I would normally accomplish the task, minus the private functions a variables, so I am at a loss as to how to accomplish this. All online resources don't seem to help. Thanks. – user1171786 Mar 17 '20 at 22:12
  • @user1171786 you can't have private variables in javascript outside of tricks as shown in the Workaround section of this answer. you just can't. you need to review the assignment and the lesson material to exact your actual goal here, and ask your professor or TA for assistance if you can't figure out what to do that **doesn't** involve something not possible in javascript – Klaycon Mar 17 '20 at 22:23
0

You can make functions "private" by wrapping them in a certain scope.

In your example that means wrapping it in an immediately invoked function expression:

(function () {
  function myFunction() {
    document.getElementById("panel").style.display = "block";
  }

  // myFunction is only available within the outer function context.
})();

This also means that the following will no longer work:

<p class="flip" onclick="myFunction()">Click to show panel</p>

myFunction is no longer publicly available, thus this will now throw an error when clicked. You could however set it through addEventListener when you are still in the same scope as myFunction:

(function () {
  function myFunction() {
    document.getElementById("panel").style.display = "block";
  }

  for(const p of document.querySelectorAll("p.flip")) {
    p.addEventListener("click", myFunction);
  }
})();
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • I edited my code to toggle now it does not work. Here is the Javascript. `````` I cannot figure out what I did wrong. – user1171786 Mar 17 '20 at 23:32
  • @user1171786 The `togglePanel` function is missing curly braces. I also assume you've removed the `onclick="..."` from the HTML and that `p.show` targets the button (this is `p.flip` in your example). Other than those things it should work. https://jsfiddle.net/7sjntck5/ – 3limin4t0r Mar 18 '20 at 08:43