Encapsulation is one of the fundamental principles of object-oriented programming (OOP) that refers to the concept of binding the data (member variable) and the methods that operate on the data (member functions) within a single unit called a class.
Encapsulation enables programmers to hide the implementation details of one object from other objects and restrict direct access to the internal state of an object.
Encapsulation provides several benefits, such as:
improving the maintainability of the code -- making it easier to modify and extend the class's functionality.
Enhancing the security of the data by preventing unauthorized access.
It also allows the programmer to use the class's interface without knowing the implementation details, which makes it easier to use and understand.
let look at an example of encapsulation in JavaScript:
function createCounter() {
let count = 0;
function increment() {
count++;
console.log(count);
}
return increment;
}
const counter = createCounter();
counter(); // Output: 1
counter(); // Output: 2
counter(); // Output: 3
In this example, we have a createCounter
function that returns an increment
function. The increment
function has access to the count
variable through a closure, but the count variable is not accessible from outside the function. The only way to modify the count
variable is by calling the increment
function, which increments the count and logs it to the console.
This is an example of encapsulation because the count
variable is hidden from the outside world and can only be accessed through the increment
function, which provides a well-defined interface for accessing and modifying the count.
In addition to using closures, another way to achieve encapsulation in JavaScript is by using setters
and getters
. Setters
and getters
are methods that allow us to control how properties are set and retrieved from an object.
Here's an example of encapsulation using setters
and getters
:
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
get name() {
return this._name;
}
set name(newName) {
if (typeof newName === "string") {
this._name = newName;
} else {
throw new Error("Name must be a string");
}
}
get age() {
return this._age;
}
set age(newAge) {
if (typeof newAge === "number" && newAge > 0) {
this._age = newAge;
} else {
throw new Error("Age must be a positive number");
}
}
}
const person = new Person("John Doe", 30);
console.log(person.name); // Output: John Doe
console.log(person.age); // Output: 30
person.name = "Jane Doe";
person.age = 25;
console.log(person.name); // Output: Jane Doe
console.log(person.age); // Output: 25
person.name = 123; // Throws an error: Name must be a string
person.age = -1; // Throws an error: Age must be a positive number
In this example, we have a Person class with name and age properties that are encapsulated using setters
andgetters
. The getters
allow us to retrieve the values of these properties, while the setters
allow us to control how they are set.
For instance, the name setter checks whether the new value is a string before setting the _name property, while the age setter checks whether the new value is a positive number. This allows us to enforce certain constraints on the values of these properties and ensure that they are always valid.
By encapsulating thename
and age
properties using setters
and getters
, we can hide their internal implementation and control how they are accessed and modified from outside the class. This helps to maintain the integrity of the object and prevent any unexpected side-effects that could result from direct manipulation of its properties.
In Summary, In encapsulation can be achieved through the use of closures and modules, as well as using setters
and getters
to control how properties are set and retrieved from an object. it also helps to improve the quality and maintainability of software systems.
Top comments (8)
I am not a fan of javascript terminology, however you wrote a nice explanation.
To me, encapsulation is just "when you use a function within a function or a class" the end.
Did you notice that there is a difference between classes and and objects? You can define a function within a class, but you cannot use it there. You will need to create an instance of the class (-> an object) to "use" a class method. But each object hast it´s individual, separated namespace and memory. THAT makes the difference.
Frankly, it makes ZERO difference in about 99% of code any of us ever write. On rare ocassions you might create something where the memory usage actually affects performance, and then you generally just rewrite it or split it into more objects or functions and get it working better.
My comment was just about how javascript terminology sucks and really we don't need many of the terms with really complicated explanations when "a function within a function or class" suffices, that's all.
Encapsulation is especially helpful if you need to maintain a larger codebase. It may help you to create better maintainable code.
As long as you need to deal with JS and HTML, your options are a bit limited, as HTML "ID´s" are always defined in a global scope. If you work with dynamically generated DOM elements, this is a different game, as you can encapsulate the DOM-references too. See this example to get an idea of the possibilities.
If you want to work seamless with OO-code on the web, you would need a framework that allows to create the DOM without HTML. There are several approaches to achieve this, like ReDom or DML, which work pretty well to create fully responsive apps.
Square peg in a round hole
ref
The browser is a machine:
The "Human Interaction Component" in the days of Coad and Yourdon (1991) was largely based on the mental model of MVC—Smalltalk. Not something like a web browser.
Progressive Misconceptions
React's component model is essentially React style OO-thinking in pursuit of the elusive (composability and) reusability benefit.
But even that component model is showing it's cracks especially when everything is dogmatically coerced into being components or hooks for the sake of interoperability with the framework (reminiscent of the early days of Java were everything had to be an object).
Sure, we need boundaries but those boundaries don't necessarily manifest themselves just in the form of objects.
Patterns for Building JavaScript Websites in 2022
Ryan Carniato for This is Learning ・ Jun 8 '22 ・ 9 min read
Application Holotypes: A Guide to Architecture Decisions
C++ is good at providing a human oriented representation of the problem in the source code but bad at providing a machine representation of the solution. So, should we use Assembler again? I assume, before ChatGPT most web designers have been humans, so what is bad about a human oriented representation of a problem?
React was not designed to deliver an "optimal" solution. It was designed to make things simpler, even at the price of a high workload to do all the DOM diffing. Browsers are so increadible powerful today, why should we need an "optimal" solution? It´s perfectly ok if it´s simple and understandable.
“… static web site. You see in the trace what's going on here is a badly configured Angular application. It's easy to fix but they just don't have a reason to care, this isn't their problem. Right, it's fast on their iPhone!”
Alex Russell - The Mobile Web: MIA - YouTube
Responsive Design didn't work, at least not the way we tried to apply it as a community. How do we know? Because nearly a decade after we adopted it as our p...
Clean Code Q & A
Clean Code Q & A Part 2
This is why performance matters
Perhaps you'd like to entertain a slightly different perspective:
"Simple Made Easy" - Rich Hickey (2011) - YouTube
Rich Hickey, the author of Clojure and designer of Datomic, is a software developer with over 30 years of experience in various domains. Rich has worked on s...