Search code examples
javascriptoopobjectencapsulationdata-hiding

Encapsulation / Data Hiding in Javascript?


I would like to understand the concept of Encapsulation in JavaScript, and how to make my properties and methods public or private.

I'm playing around with this example:

    var person = function(newName, newAge) {

    // Private variables / properties
    var name = newName;
    var age = newAge;

    // Public methods
    this.getName = function() {
        return name;
    }

    // Private methods
    var getAge = function() {
        return age;
    }

    // Public method, has acces to private methods
    this.giveAge = function() {
        return getAge();
    }
}

var jack = new person("Jack", 30);

console.log(jack.name); // undefined
console.log(jack.getName); // Jack
console.log(jack.getAge()); // TypeError: jack.getAge is not a function
console.log(jack.getAge); // undefined
console.log(jack.giveAge()); // 30

So, variables var name and var age are private. To access them I use public methods by using .this reference. So anything that is var inside my function is private, and anything that's .this inside my object is visible outside.

I guess that's cause person is visible, so it exposes all of its properties.

Am I on the right track? Is this the right way to hide or expose your properties / methods?

And one more question, why does console.log(jack.getAge()); throws an error? And when referencing functions I "stored" in variables, should I put () at the end of that function, it works both ways, so I don't know what do use?

Thanks!


Solution

  • I guess that's cause person is visible, so it exposes all of its properties.

    Correct.

    Am I on the right track? Is this the right way to hide or expose your properties / methods?

    If you want to do it, then yes, this is a fairly standard way to do it. There's at least one other way as of ES2015, but with (probably) more overhead.

    And one more question, why does console.log(jack.getAge()); throws an error?

    Because the jack object doesn't have a getAge property, so jack.getAge yields undefined, which isn't a function. There's a getAge variable inside the context that the giveAge closure has access to (along with age and name), but jack doesn't have a getAge property.

    And when referencing functions I "stored" in variables, should I put () at the end of that function, it works both ways, so I don't know what do use?

    No, it doesn't work both ways. jack.getName gets a reference to the function. jack.getName() calls the function and gets its return value.

    I should note that there's no point to the getAge function. It's only accessible to closures defined within the person function, just like age and name are. So anything that would use getAge would just use age instead and avoid the function call.


    Just for completeness, I'll note that many people don't worry about truly private properties in JavaScript, opting instead for "private by convention" — e.g., they use a naming convention (such names starting with _) to mean "don't touch these, they're private." That doesn't do anything to prevent people using them, of course, it just indicates that they shouldn't. Folks advocating this usually point out that in many languages with "true" private properties/fields (Java, C#), those properties/fields are accessible with only a small amount of effort via reflection. And so, the argument goes, just using a naming convention is "as private."

    I'm not agreeing (nor particularly disagreeing) with that, it does require rather more work in Java or C# to access private properties than public ones. I'm just noting that the "private by convention" approach is quite common, and frequently "good enough."