2

How to create private variables and methods using ES6 class which should be access by public methods of the same class.

class MyClass {
    constructor() {
        this.publicVar = "I am public";
        //some private Variable e.g privteVar1 = "I am Private1"; privateVar2 = "I am Private2";
        this.publicMethod = () => {
         //it should have accesses to private variables and methods
           console.log(privateVar1, privateVar2)
        }; 
        //similarly need to create some privateMethod           
    }

    render() {
         //it also should have access to the private variables
    }

}
Mousey
  • 1,855
  • 19
  • 34
jrath
  • 980
  • 4
  • 14
  • I checked the same. But not clear. It would be great If someone helps me in this particular example I have given. – jrath Jul 21 '15 at 23:02
  • Exactly the same way you did before. Or use what is suggested in the linked question. Also see http://stackoverflow.com/q/30191656/218196 – Felix Kling Jul 21 '15 at 23:08

5 Answers5

3

As noticed by @yibuyisheng you can use symbols to create unaccessible references to properties. Also you can create private method as well.

var privateMethod = Symbol('private');

class SomeClass {
  constructor() {
  }

  [privateMethod]() {
    // some private actions
  }

  render() {
    // call private method
    this[privateMethod]()
  }
}

Symbol creates a unique reference and it can be used as property name. And this property or method could be called only by using it. It is possible because ES6 is introducing computed properties syntax and you can use variables for dynamic properties definition.

If you are not exposing this symbol for others, only you can call it.

just-boris
  • 9,468
  • 5
  • 48
  • 84
  • No. Symbol keys are public just as string property names are, and can be enumerated. You cannot hide them. – Bergi Jul 22 '15 at 20:20
  • Nope. Class methods is not iterable by spec. See babel-repl example: http://bit.ly/1SCI5rD – just-boris Jul 22 '15 at 20:36
  • I didn't mean to say that they were enumerable with a `for in` loop (no methods are, you don't need symbols for that). I said that [symbols are just as exposed as normal properties](https://babeljs.io/repl/#?evaluate=true&code=var%20privateMethod%20%3D%20Symbol('private')%3B%0A%0Aclass%20SomeClass%20%7B%0A%20%20%5BprivateMethod%5D()%20%7B%0A%20%20%20%20%2F%2F%20some%20private%20actions%0A%20%20%7D%0A%7D%0A%0Avar%20keys%20%3D%20Reflect.ownKeys(SomeClass.prototype)%0Aconsole.log('accessible%20keys'%2C%20keys)%3B%0Aconsole.log('%22private%22%20method%3A'%2C%20(new%20SomeClass)%5Bkeys%5B1%5D%5D)) – Bergi Jul 22 '15 at 20:50
  • Fine, you can extract it from outside. But you have to do a few special tricks for it and you aware what are you doing. Symbol-way privates can't be accessed occasionally and it seems to be enough for most purposes. Also you haven't to use `bind` or `apply` when you calling private methods, but you have to do it when you storing methods in `WeakMap` inside closure – just-boris Jul 22 '15 at 20:59
  • Well, you hardly access any properties of objects you don't own "accidentally" - you do it on purpose anyway, and that's what a *private* property is trying to prevent. – Bergi Jul 22 '15 at 21:05
2

Just make it a local variable, with var/let/const, and it will be available through closure from all the privileged methods you define in your constructor. This has not changed from ES5, btw.

class MyClass {
    constructor() {
        this.publicVar = "I am public";
        const privateVar1 = "I am Private1",
        const privateVar2 = "I am Private2";
        this.publicMethod = () => {
            // it has access to private variables
            console.log(privateVar1, privateVar2)
        };          
    }
}

Notice that those variables are local to the constructor, so you cannot access them from your prototype methods, for those you would need public properties or complicated workarounds.

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • What if I need to access the privateVar, outside of constructor() i.e.in some other method of the same class? In that case privateVar is undefined. – jrath Jul 21 '15 at 23:19
  • Please refer my edited question I added render() outside of constructor. there also I need to access the private variables. – jrath Jul 21 '15 at 23:25
  • @jrath: `render` is a prototype method, I've already commented on those. Move it in the constructor, or switch from variables to public properties. – Bergi Jul 22 '15 at 00:12
1

You can use Symbol to implement it like this:

var privateSymbol = Symbol('private');

class SomeClass {
  constructor() {
    this.setPrivateValue('some init value');
  }

  setPrivateValue(value) {
    this[privateSymbol] = value;
  }

  getPrivateValue() {
    return this[privateValue];
  }
}

Note that put the previous codes in some module, and do not expose the privateSymbol.

yibuyisheng
  • 149
  • 8
0

The only way to get true privacy in JS is through scoping, so there is no way to have a property that is a member of this that will be accessible only inside the component. The best way to store truly private data in ES6 is with a WeakMap.

const privateProp1 = new WeakMap();
const privateProp2 = new WeakMap();

class MyClass {
  constructor() {
    privateProp1.set(this, "I am Private1");
    privateProp2.set(this, "I am Private2");

    this.publicVar = "I am public";
    this.publicMethod = () => {
      console.log(privateProp1.get(this), privateProp2.get(this))
    };        
  }

  render() {
    //it also should have access to the private variables
    console.log(privateProp1.get(this));
  }

}
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • I didn't say it was perfect, but in my mind, it's the only way to get true privacy without incurring costs elsewhere. Capturing the variables in the constructor works, but then you have up-front costs of creating new function expressions, and you loose many of the benefits of class syntax. – loganfsmyth Jul 22 '15 at 02:39
  • Oh forget it. Somewhere I read that weakmaps cause deoptimisations and incur some extra, unexpected cost on the garbage collector, but I cannot find that reference any more, I must misremember that. Now my only distaste is about their ugly syntax :-/ – Bergi Jul 22 '15 at 03:11
  • Can't argue there, hahah. – loganfsmyth Jul 22 '15 at 04:37
  • Ah, found it: https://github.com/kriskowal/q/issues/712 – Bergi Jul 22 '15 at 05:53
-4

Try this:

console.log(this[privateVar1], this[privateVar2])

Call your properties like this[myPrivate]. This is the way to make your properties a some kind of private. But this syntax does not provide true privacy.

Dmytro
  • 39
  • 7