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!
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."