Private properties for ES6 JavaScript

In ES5 JavaScript, it is relatively easy to have private properties in prototype definition.

It goes like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// es5 constructor(as class) definition 
// JavaScript is prototype-based language
function Person(firstname, lastname) {

// public property
this.firstname = firstname;
this.lastname = lastname;

// private property
var records = [{type: 'in', amount: 0}];

// public function
// it needs to be instance method to access private properties
this.addTransaction = function(trans) {
if (trans.hasOwnProperty('type') && trans.hasOwnProperty('amount')) {
records.push(trans);
}
}

// public function
this.getBalance = function() {
var total = 0;

records.forEach(function(record){
if (record.type === 'in') {
total += record.amount;
} else {
total -= record.amount;
}
});

return total;
}
}

// Prototype function
Person.prototype.getFullName = function() {
return this.firstname + " " + this.lastname;
};

module.exports = Person;

Although, in es6, it is not that easy to achieve and there are many options you can choose.

You can find all of those here, Managing private data, JS class definition

In my opinion, weekmap method is the best, if you need perfect privacy. Other than that, you could use conventional approach using underscore(_) in front of private property names.

But I found most cases can be solved by modularity approach which looks something like the code below.

In a file such as person.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

let records = [{type: 'in', amount: 0}];

export class Person {

constructor(first, last) {
this.firstname = first;
this.lastname = last;
}

addTransaction(trans) {
if (trans.hasOwnProperty('type') && trans.hasOwnProperty('amount')) {
records.push(trans);
}
}

getBalance() {
let total = 0;

records.forEach(record => {
total += record.amount;
});

return total;
}

getFullName() {
return `${this.firstname} ${this.lastname}`;
}

}

record property is used as a private data storage and can NOT be accessed out of the modular scope.

To use this class, you can just import and use. Below are unit tests that I wrote against to the Person class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { Person } from './person.js';

describe('Person es6 class', function () {

var person;
beforeEach(function () {
person = new Person('Andrew', 'Lincoln');
});

it('should be initiated with first name and last name', function () {
expect(person.getFullName()).toEqual('Andrew Lincoln');
});

it("should be initiated with 0 balance", function() {
expect(person.getBalance()).toEqual(0);
});
});

Hope this helps.

Share