Search code examples
javascriptoopprivate

What "private property" means on ES6 classes?


I am a bit lost with ES6 privacy on Classes. I have this Class:

class Whatever {

        constructor(value) {
            this._value = Number(value);
        }

        total() {
            return this._value * 2;
        }
    }

    let instance = new Whatever('1000');
    console.log(instance.total() );     // 2000     
    console.log(instance._value  );     // 1000

I am trying to learn how Symbol() works to keep data private (see link), and after reading the documentation I am trying to make a simple example about it, but does not seem to have any difference:

const _value = Symbol('value');

    class Whatever {

        constructor(value) {
            this[_value] = Number(value);
        }

        total() {
            return this[_value] * 2;
        }
    }


    let instance = new Whatever('1000');
    console.log(instance.total() );     // 2000     
    console.log(instance[_value]  );    // 1000

Could someone explain me on a comprehensive way, what does privacy mean on this case, and why my idea of privatizing data (making data unaccesible from outside the Class) is wrong? I have not much experience on OOP.

Thank you.


Solution

  • No real difference in your example, assuming you don't loop through the enumerable properties of the class.

    Consider the following:

    function MyFunction () {
      const _private = new Symbol();
    
      this[_private] = 5;
      this.public = 10;
    }
    
    const thing = new MyFunction();
    
    for (let key in thing) { // prints 10
      console.log(thing[key]);
    }
    
    console.log(thing.public); // prints 10
    console.log(thing._private); // undefined
    

    Properties named by symbols are not enumerable, so in a sense they're not "exposed". Another benefit of symbols is that they're guaranteed to create unique keys, so there's no worry of key name collisions.

    I chose to illustrate it with a function rather than a class for simplicity sake. For a class you could do the following (it's all about scope for "protecting" the symbol):

    const MyClass = (function () {
      const _value = Symbol();
      return class _MyClass {
        constructor() {
          this[_value] = 5;
        }
      }
    })();
    

    Disclaimer: It's not "true" privacy, since there are still ways to enumerate the symbols. I think the biggest advantage is for the name collisions.