7

I know that there is no REAL private method INSIDE ES6 classes. However I was playing around a little bit and discovered something good - maybe...

As I mentioned it is not possible to not expose properties of an object. But I've tried to achieve somewhat of OOP programming as I divided my classes into seperate files and then exported those classes like:

class MyClass {
  constructor() {
    /**
     * Initialize stuff...
     */
  }

  myMethod() {
    /**
     * Do public stuff...
     */
  }

}

// expose class to environment.
export default MyClass;

So I can import the class:

import MyClass from './MyClass.js';

Of course myMethod is accessible from any other file which imported the module. Sinced I was in need of variables and functions beeing accessible only by the class I've tried this:

// private variable outside of class scope but still accessible.
let possiblePrivateVariable = 'am I a private variable?';

class MyClass {
  constructor() {
    /**
    * Initialize stuff...
    */
  }

  myMethod() {
    // run private method.
    console.log(_possiblePrivateMethod());
    // show private variable.
    console.log(possiblePrivateVariable);
  }

}

// private function outside of class scope but still accessible.
function _possiblePrivateMethod() {
  return 'am I a private method?';
}

// expose class to environment.
export default MyClass;

Now you can't access the private variable and private method:

// Import class to newFile.js and use it.
import MyClass from './MyClass.js';

const exposedClass = new MyClass();
exposedClass.possiblePrivateVariable;   // -> undefined.
exposedClass._possiblePrivateMethod();  // -> undefined.
exposedClass. myMethod();               // -> logs: am I a private method?
                                        //          am I a private variable?

It is obvious that those are feeling like beeing 'private' because I am not exposing them with the word export. My question is if this method can be considered creating private variables and methods? And if the Method I've shown has any other possible leakage while running the code?

Regards, Megajin


Sidenote: I do not need browser support since it is a NodeJS only environment. I am using NodeJS v8.1.4 and use babel in my npm start script so I can use import without any TypeError's.

I should mention as well that I'm aware that this question could be seen as a duplicate but it is not because this question is not about private properties, variables and methods inside a class but outside it.

Megajin
  • 2,648
  • 2
  • 25
  • 44
  • 1
    Well, yes, but… that "private" variable is shared between all instances of the class. Which defeats the purpose of having a class with potentially several independent instances. You've just reduced it to a (non-)global variable. – deceze Aug 23 '17 at 08:20
  • 1
    Those are no methods, they're not part of the instances. They're just static functions and variables local to the module. Which is fine, but most likely not what you were looking for. – Bergi Aug 23 '17 at 08:30
  • @deceze If I have 2 instances of the same class will the variables be overwritten by each other? – Megajin Aug 23 '17 at 09:07
  • @Bergi I see you are feeling what I'm trying to do. How would you approach this given problem? – Megajin Aug 23 '17 at 09:09
  • Yes, the variable exists only once, not once per instance. – deceze Aug 23 '17 at 09:12
  • @deceze would you say that if I make sure that the class will be instantiated only once the given approach is sufficient? – Megajin Aug 23 '17 at 09:18
  • I would question why you're bending over backwards like this in the first place. – deceze Aug 23 '17 at 09:18
  • @deceze good question. I was thinking that in bigger environments with a huge usergroup and unser inputs there could be a potential risk of bugs where someone could inject JavaScript code and access those methods to go even deeper like a mongoDB connector. That was just one scenario where I went paranoid... But please keep in mind it is just my desire to know If I can overcome this problem, I am well aware that JavaScript has its restrictions. – Megajin Aug 23 '17 at 09:29
  • 3
    Your outward API, e.g. your HTTP interface, should be resistant to stuff like injection. Your inner API, which presumably is only accessible to developers you trust, doesn't need to be ironclad fortified against itself. Typescript's `private` annotations, or perhaps a simple naming convention like `_thisIsPrivate`, are enough to ensure privacy. **Privacy is not a security mechanism** in the first place; it's to keep code maintainable and extensible by defining stable public interfaces and unstable internal implementation details. – deceze Aug 23 '17 at 09:35
  • Yes you are right, privacy is not a security mechanism in the first place. I might've used a bad example here. Imagine that in a really huge project with alot of developers someone could accidentally use a function which should only be accessed within the class. Under the very rare circumstances, where this accident is working well and is going through the code reviews and also every test, a bug could appear in later releases which could cost you days of searching... especially in JavaScript. – Megajin Aug 23 '17 at 09:49
  • 1
    You can't protect against developer stupidity. There are many more worse things any developer will do that will cost you time here and there. This is a problem to be solved at the process level (workflow), not the code level. E.g. have a CI server which compiles TypeScript and reports errors; if you're correctly using `private` annotations, that'll catch that kind of problem. – deceze Aug 23 '17 at 09:53
  • You lowered my paranoia and I'm starting to think about another problem which I could solve with an code review AI... I'm glad that we talked about this, thank you very much. – Megajin Aug 23 '17 at 13:22

1 Answers1

6

My question is if this method can be considered creating private variables and methods?

Yes it's an actual working solution to address the fact that ES6/7/8 do not handle privacy in classes.

And if the Method I've shown has any other possible leakage while running the code?

Fast answer : No leak

Detailed answer:

In your private function system, what makes the function private is that in javascript the scope of a function is defined by where it's defined. In your case the file.

If you do not export the function outside the file, there is no way to access it. Like you cannot access the function in the following mainstream example :

function toto() {
 const tmpToto = () => console.log('Hello');

 // I can access tmpToto from here
 tmpToto();

 return false;
}

// I cannot access tmpToto from here

Here you get a nice explanation about scopes


More infos according to comment

How would you solve the problem that multiple class instances will share the 'out of scope' variables?

You can use IIFE(Immediately-invoked function expression) as described by @Son JoungHo in this post.

let Name = (function() {
  const _privateHello = function() {}

  class Name {
    constructor() {}

    publicMethod() {
      _privateHello();
    }
  }

  return Name;
})();
Orelsanpls
  • 22,456
  • 6
  • 42
  • 69
  • Because of how scopes work in JavaScript I came up with my idea. How would you solve the problem that multiple class instances will share the 'out of scope' variables? – Megajin Aug 23 '17 at 09:22
  • 1
    You could have an array where you store values, managing this with the constructor. – Liam MacDonald Aug 23 '17 at 09:31
  • 1
    @LiamMacDonald that's pretty clever I'm going to use that idea as well for another problem I had. – Megajin Aug 23 '17 at 09:42
  • 1
    IIFEs are mostly pointless here. The OPs code that puts a class in a module (with its own scope) is doing just the same. – Bergi Aug 23 '17 at 17:55
  • 1
    Not if he do instantiate the class multiple time. possiblePrivateVariable will be common to all class instance – Orelsanpls Aug 24 '17 at 08:34