Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoffeeScript Private Class Instance Variables

I have the following CoffeeScript code:

class Person
  secret = 0
  constructor: (@name, @age, @alive) ->
  inc: -> secret++

Which compiles to the following JavaScript code:

var Person;
Person = (function() {   
    var secret;
    secret = 0;

    function Person(name, age, alive) {
        this.name = name;
        this.age = age;
        this.alive = alive;
    }
    Person.prototype.inc = function() {
        return secret++;
    };
    return Person;
})();

Currently secret is shared between all instances of Person. Is there a way to make secret a private instance variable in CoffeeScript?

like image 965
knpwrs Avatar asked Mar 27 '12 09:03

knpwrs


People also ask

How do you declare private variables in classes in JavaScript?

Private instance fields are declared with # names (pronounced "hash names"), which are identifiers prefixed with # . The # is a part of the name itself. Private fields are accessible on the class constructor from inside the class declaration itself.

Are JavaScript variables private?

In its current state, there is no “direct” way to create a private variable in JavaScript.

How can you implement private methods in JavaScript es5?

In a JavaScript class, to declare something as “private,” which can be a method, property, or getter and setter, you have to prefix its name with the hash character “#”.

How do you make a property method private in ES6?

Short answer, no, there is no native support for private properties with ES6 classes. But you could mimic that behaviour by not attaching the new properties to the object, but keeping them inside a class constructor, and use getters and setters to reach the hidden properties.


3 Answers

I figured out a solution. I am not sure if this is the best solution, so I am still open to others.

CoffeeScript:

class Person
  constructor: (@name, @age, @alive) ->
    secret = 0
    @inc = -> secret++;

JavaScript:

var Person;
Person = (function() {
    function Person(name, age, alive) {
        var secret;
        this.name = name;
        this.age = age;
        this.alive = alive;
        secret = 0;
        this.inc = function() {
            return secret++;
        };
    }
    return Person;
})();
like image 139
knpwrs Avatar answered Nov 06 '22 06:11

knpwrs


There is no concept of private members in CoffeeScript as there is none in JavaScript. There are local variables, which you do utilize well in your own solution, but while your solution does hide the secret variable from anything outside of a constructor function, it also introduces an overhead of redeclaring the inc method on every instantiation of a class Person.

A mistake very common in JavaScript community is trying to project inexistent features of other languages on it, which an attempt of mimicing private members is obviously a case of. There's no such concept in it and thinking deeper you'll conclude that it would be just unnatural to an extremely loose dynamic environment which JavaScript is.

So don't waste your time and performance of your application on implementing inexistent constructs. Just concentrate on solving your problem - not the problems of lacking language features.

Now ask yourself: what is so hurtful in having all members public?

Taking everything said into account the ultimate solution would be:

class Person
  constructor: (@name, @age, @alive) ->
    @secret = 0
  inc: -> @secret++
like image 20
Nikita Volkov Avatar answered Nov 06 '22 06:11

Nikita Volkov


While it won't truly hide them, the convention is to prefix "private" members with an underscore. The idea here is that folks consuming this should assume that such members are implementation details and are advised not to use them.

like image 21
Larry Maccherone Avatar answered Nov 06 '22 06:11

Larry Maccherone