DEV Community

Cover image for You Can Create Private Properties In JS (accessor pattern)

You Can Create Private Properties In JS (accessor pattern)

Kirill Shestakov on April 09, 2017

It's very common for JavaScript developers to claim that it's impossible to create truly encapsulated properties and methods on an object and use...
Collapse
 
benaryorg profile image
#benaryorg

I haven't extensively worked with JavaScript, so out of curiosity:
JavaScript is readable by anyone with access to the source code, including the user in most cases.
Why would I go through all of this?
I don't see a reason to restrict access to any property of an application, besides the obvious "Don't touch it" which I usually solve using some sort of PEP 8 naming scheme.
I can imagine that maybe there are security critical applications (think of maybe E2E encrypted messaging) that want to prevent encryption keys to be accessible by injected JavaScript, but that's about it. (EDIT: that however seems to be more of a security through obsurity kind of thing)

Am I overlooking something here?

Collapse
 
guitarino profile image
Kirill Shestakov

You're right that the source code is available to everyone and that people can just step through your code and gain access to any object or a variable they encounter. But there's still importance in making properties private as a means to distinguish between a property people can change, play around with and a property that is exposed to the public yet people shouldn't touch. Example: suppose you're creating a Class and publishing it as a library. Users of the library can use your Class to create instances that will have some properties. You might want to have some properties per each Class instance that you don't want people to mess with, in which case it makes sense to make them private. I don't think this solution can help with security though.

Collapse
 
benaryorg profile image
#benaryorg

Wouldn't a convention/readme saying "don't touch references starting with an underscore" suffice for that?
Building wrappers and doing language-magic seems a bit overkill.

Thread Thread
 
guitarino profile image
Kirill Shestakov

If it suffices for you to just mention it in Readme, good. It's probably not enough for me.

Also, the method I described doesn't require you to do wrappers. It requires you to create a closure, but you should probably have it anyway (module pattern).

Collapse
 
jpstone profile image
Justin Stone

Prototypes can be simply avoided 99.99999999% of the time. The vast majority of prototypes I see in code could have been done compositionally instead.

Collapse
 
guitarino profile image
Kirill Shestakov

When you're creating Web Components, I don't think you can avoid using prototypes.

That's true in general though, and many people just use factory functions instead as a practice. That's cool, if you can afford it. I still think it's beneficial for people who use prototypes to know this method.

Collapse
 
jpstone profile image
Justin Stone

"When you're creating Web Components, I don't think you can avoid using prototypes."

Why not? Genuinely curious...

Thread Thread
 
guitarino profile image
Kirill Shestakov

When you're creating Web Components, you have to inherit native HTML element prototype such as HTMLElement or HTMLInputElement, etc. So you'd have to do something like this:

customElements.define('my-element', class extends HTMLElement {
    constructor() {
        super();
        console.log('test');
    }
});
Enter fullscreen mode Exit fullscreen mode

There's really no way to avoid it here with a factory function. You can probably just define all the properties and methods inside the constructor instead of defining it on the prototype (inside class), but there's no benefit to it performance-wise and you can't make the constructor a factory function since you can't return a new object.

Thread Thread
 
jpstone profile image
Justin Stone

Out of curiosity, why not just do something like:

function myCustomElement() {
  // happy closures go here

  return {
    someTypeOfMetaData,
    someUtilityFunction,
    HTMLElement,
  };
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
guitarino profile image
Kirill Shestakov

This won't help you create a custom element, nor register it. Read more about Web Components.