Encapsulation means information hiding. It’s about hiding as much as possible of the object’s internal parts and exposing a minimal public interface.
Encapsulation means information hiding. It’s about hiding as much as possible of the object’s internal parts and exposing a minimal public interface. The simplest and most elegant way to create encapsulation in JavaScript is using closures. A closure can be created as a function with private state. When creating many closures sharing the same private state, we create an object.
JavaScript offers a unique way for creating encapsulated objects using factory functions. Objects encapsulate state.
// USING A FACTORY FUNCTION
function Stack(){
let list = [];
function push(value){ list.push(value); }
function pop(){ return list.pop(); }
return Object.freeze({
push,
pop
});
}
let stack = Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.pop(); //3
stack.pop(); //2
stack.list; //undefined
stack.list = 0;//Cannot add property list, object is not extensible
class Stack {
constructor(){
this.list = [];
}
push(value) { this.list.push(value); }
pop() { return this.list.pop(); }
}
let stack = new Stack();
stack.push(1);
stack.push(2);
stack.list = 0; //corrupt the private state
console.log(stack.pop()); //this.list.pop is not a function
function Queue(){
let list = [];
function enqueue(value){ list.push(value); }
function dequeue(){ return list.shift(); }
return Object.freeze({
enqueue,
dequeue
});
}
let queue = Queue();
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
queue.dequeue(); //1
queue.dequeue(); //2
queue.list; //undefined
function EventEmitter(){
let subscribers = [];
function subscribe(type, callback){
subscribers[type] = subscribers[type] || [];
subscribers[type].push(callback);
}
function notify(value, fn){
try {
fn(value);
}
catch(e) { console.error(e); }
}
function publish(type, value){
if(subscribers[type]){
let notifySubscriber = notify.bind(null, value);
subscribers[type].forEach(notifySubscriber);
}
}
return Object.freeze({
subscribe,
publish
});
}
let eventEmitter = EventEmitter();
eventEmitter.subscribe("update", doSomething);
eventEmitter.subscribe("update", doSomethingElse);
eventEmitter.subscribe("add", doSomethingOnAdd);
eventEmitter.publish("update", {});
function doSomething(value) { }
function doSomethingElse(value) { }
function doSomethingOnAdd(value) { }