Javascript - Protecting Your Data
Making data private
- Use closures
- Closures hide long-lived data from interference
Example
function Account(initialBalance) {
var balance = initialBalance; // Deep copy if by reference
return {
getBalance: function() {
return balance;
},
setBalance: function(newBalance) {
if (newBalance > 0) {
balance = newBalance;
}
}
}
}
var account = Account(100);
console.log(account.getBalance()); // 100
100
Accessor properties
- Make attributes hidden behind a function, and hence immutable (or checked for mis-access)
- Useful strategy to even handle existing attributes
Example
function Person(firstName, lastName) {
return {
get firstName() { return firstName; },
set firstName(newFirstName) { return undefined; },
get lastName() { return lastName; },
set lastName(newLastName) { return undefined; }
}
}
var person = Person('Ravindra', 'Jaju');
console.log(person.firstName);
Ravindra
Making data immutable
- Object.defineProperty is your friend
Example
var o = {}
Object.defineProperty(o, 'property', {
value: "I am valuable!",
writable: false
});
o.property; // I am valuable!
o.property = "I am not valuable!"; // Check. No change!
console.log(o.property);
I am valuable!
Pitfalls
- Javascript will not inform you on errors.
- Modify immutable attribute - no throw!
- Call setters which are no-ops - no throw!
Deep clone
- Javascript passes objects by reference
- You have no control over who keeps the reference
- Modification can happen behind your back
- Surprises!
Solution?
- Poor man's deep clone
let o = {key: "value", truthy: true};
console.log(JSON.stringify(o))
console.log(JSON.parse(JSON.stringify(o)))
{"key":"value","truthy":true} { key: 'value', truthy: true }
-
It does not copy non-data attributes
- Functions, getters/setters are lost