0

Take that you want a single JavaScript object that offers some methods, like this:

var a = {
    c: "hello",
    talk: function(){
        console.log(this.c);
    }
}

But you don't want people to be able to access c directly, you want it to be sort of private. I've figured out this solution, but I don't know if there are any better ones:

var a = new function(){
    var c = "hello";
    this.talk = function(){
        console.log(c);
    };
}

Can you think of a better solution? And can you tell why it is better?

Could you point any (performance, mantainability, or other) trouble this approach can give me?

I leave here an extra example in which I think this could be conceptually usefull:

var Animation = {
    from_right: "translate(100%,0)",
    from_bottom: "translate(0,100%)",
    zoom: "translate(0,0) scale(0)",
    default: "translate(100%,0)",
    get_initial: function(type){
        switch (type) {
            case "from_right":
            case "from_bottom":
            case "zoom":
                return this[type];
                break;
            default:
                return this["default"];
                break;
        }
    },
    get_final: function(){
        return "translate(0,0) scale(1)";
    }
}

I know this works perfectly like this but, for me, conceptually, it is much clearer when using or reviewing it to have those first config properties as private variables. For example, if I log Animation and find that it has 2 methods, I realise faster how to use it than if all those properties that are not supposed to be accessed are printed as well. It is not about how to do something, it is about how to do it clearer and better.

Thanks!

Vandervals
  • 5,774
  • 6
  • 48
  • 94
  • 8
    First step: Why is it that important that `c` be "private" to begin with? Yes, encapsulation gives you "privacy" (note the quotes), but it also forces you to bend over backwards in terms of your coding. Unless you have a really really good reason, my advice on this question is always to *simply not worry about it.* – deceze Jan 17 '17 at 13:06
  • 1
    This is correct. Anything exposed at the top level as a variable is private. This works great if using getters & setters. @deceze you would want to do this if you don't someone manipulating that particular value and want it immutable. – Drew Dahlman Jan 17 '17 at 13:07
  • Related: http://stackoverflow.com/questions/6799103/how-to-set-javascript-private-variables-in-constructor also http://stackoverflow.com/questions/55611/javascript-private-methods – Turnip Jan 17 '17 at 13:07
  • Related: http://stackoverflow.com/a/37835951/476 – deceze Jan 17 '17 at 13:08
  • You can use "Closures", A good read [Hiding Your Privates with JavaScript](https://davidwalsh.name/javascript-private) – Satpal Jan 17 '17 at 13:08
  • I would start with Crockford's teachings on the subject, namely his module pattern. http://javascript.crockford.com/private.html – Tim Consolazio Jan 17 '17 at 13:08
  • I hope you're doing this for code correctness and not security purposes. Any browser with a debugger will be able to get inside any "scope wrappings" you create. – Carcigenicate Jan 17 '17 at 13:13
  • @Drew Who would manipulate that value? Other programmers? Establish a naming pattern/documentation/communication of what should and shouldn't be done. Or use TypeScript et al. which catches such things for you. Somebody poking around their browser's debugger? You can't prevent that either way. – deceze Jan 17 '17 at 13:14
  • @Vandervals Read about [Object.defineProperty.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) – Smiranin Jan 17 '17 at 13:19
  • Who are those "people" you are afraid about ? Also it would seem that your "solution" has little chance to even run. Maybe you'd want to post a revised version for clarity. – Éric Viala Jan 17 '17 at 13:24
  • @deceze as Sheldon Cooper (&friends) say, I do it because I can! So it is not about why doing it, but about finding out different ways of doing it. Now, if you ask me why, as lenguages like Java have private variables and methods, I think it is legitimate enough to have those here as well. There is nothing you can't do without them, but they are at least conceptually helpful, I believe. Also: Turnip it is not about how to create a class or instances, I know how to do that, I've made the word **single** bold because of something. – Vandervals Jan 17 '17 at 13:52
  • @Vandervals I think you could have picked better arguments : sure you can do what you want, but people you ask help to might appreciate a better reason to spend their time ("because it's an interesting challenge" would have essentially meant the same but have been so much more enticing !). Also the parallel with Java's private modifier is dubious as best since it applies to the concept of class, while here you want to modify the visibility around the concept of scope. Now I agree I'm being pedant, and wish you to obtain a satisfying answer to your question :) – Aaron Jan 17 '17 at 14:03
  • @Aaron, you are right, but I thought it was understood that this was a chance to learn, to expand knowledge, to be creative and find better ways of thing things while understanding the pros and cons. About Java, you are right as well, but I still find usefull to think of accessible info and public one. I'll edit my question adding some of those things. – Vandervals Jan 17 '17 at 14:10
  • 2
    @Vandervals I'm not very knowledgeable in this topic but I believe the main argument for "hidden" variables (for lack of a better term) is to preserve the coherency of your algorithm, while you will expose some parameters in order to enable configuring the algorithm. You want a module or piece of code you provide to other developers (or even to "future yourself") to be flexible enough to accommodate their needs, but strict enough that it will not deviate from its stated purpose in ways that you wouldn't want to document, and the developer "configuring" it might not expect – Aaron Jan 17 '17 at 14:25
  • @deceze just for sanity and clarity. Why have internal things floating around in the namespace. keep it clean and private and you're all set. Also it protects you, say you want to be using it in other methods and avoid any manipulation. – Drew Dahlman Jan 18 '17 at 16:21
  • @Drew That's all good, except that Javascript has no direct notion of private properties and all workarounds require you to bend over backwards and either result in clunky code or some other drawback. At which point you'll have to ask yourself: is it really worth it? – deceze Jan 18 '17 at 16:25
  • @deceze using getters and setters makes that really nice to work with and again you gain a clear codebase that is easy to read. – Drew Dahlman Jan 18 '17 at 17:29
  • @DrewDahlman Getters and setters don't really replace private properties, they amend them if anything. – deceze Jan 18 '17 at 17:34
  • 1
    @deceze totally, but again for sanity. also a private variable does somewhat exist if it's scoped inside the closure. It's only accessible to that particular scope, nothing outside of that could access it, nor could a user. There are use cases for doing this. One of the biggest being not polluting the namespace. – Drew Dahlman Jan 18 '17 at 17:36
  • @DrewDahlman Yes, but replacing everything with closures is what I consider very clunky code, and it has performance implications vs. prototyped methods (how *much* is arguable). And a user will still be able to futz with those variables in their debugger. – deceze Jan 18 '17 at 17:39
  • I feel this argument is becoming opinion based... deceze, even if you don't recomend it, the question is about if it is possible and how to do it. Maybe it is not an approach you'd use, but I'm sure that, with all your experience, you have the knowledge to offer a solution meeting the conditions on the question better than the clunky one I found, either you'd use it or not for your own code. – Vandervals Jan 19 '17 at 11:10

1 Answers1

0

You can use IIFE to make a closure to protect your variable

var MyClass = (function(){
    var myPrivate = "hello";
    return function(){
        this.talk = function(){
            console.log(myPrivate);
        };
    }
})();

var instance = new MyClass();
instance.talk();
gwokae
  • 76
  • 4
  • I know how to make clases, I just want one single object. – Vandervals Jan 17 '17 at 13:53
  • actually javascript is prototype-based inheritance which means you are inherit from another object. Anyway, you can simply return a js object in your IIFE instead return a contructor – gwokae Jan 17 '17 at 14:48