Sharing and Encapsulation: Prototype, Class, and IIFE in JavaScript
Instead of creating the same method for every instance, share it on the Prototype, and close the scope with an IIFE for values that need to be hidden.
Share identical methods via Prototype to save memory, and protect private data using IIFE (Immediately Invoked Function Expression). ES6 Class is a syntactical tool that wraps these concepts elegantly.
Background: Memory Efficiency and Data Protection
If you define methods inside a constructor, every instance gets its own copy, wasting memory. Furthermore, standard JavaScript objects historically lacked private fields, making IIFE necessary for encapsulation.
Core Concepts
1) The Power of Prototype
Objects created from the same constructor can share methods through the .prototype object.
function Person(name) {\n this.name = name;\n}\n\n// Shared method via prototype\nPerson.prototype.sayHi = function() {\n console.log(`Hi, I'm ${this.name}`);\n};→ Expected Result / What Changed:
Even with 10,000 instances, the sayHi method exists only once in memory.
2) Encapsulation with IIFE
To create “private” variables that cannot be accessed from outside, use an IIFE to close the scope.
const Counter = (function() {\n let count = 0; // Private variable\n\n return {\n increment() { count++; },\n getCount() { return count; }\n };\n})();→ Expected Result / What Changed:
The count variable is completely hidden from the global scope, preventing accidental modification.
3) The Modern Class Syntax
ES6 Classes provide a cleaner syntax to manage prototypes and constructors. Modern JavaScript also supports private fields using the # prefix.
class Person {\n #age = 30; // Truly private field\n\n constructor(name) {\n this.name = name;\n }\n\n sayHi() {\n console.log(`Hi, I'm ${this.name}`);\n }\n}Solution Approach
- Memory Efficiency: Use Prototypes (or Class methods) for repeatable functions to avoid bloating memory.
- Privacy First: Use IIFE or Private Fields (#) to protect sensitive data from accidental mutation.
- Readability: Leverage ES6 Classes as "Syntactic Sugar" to make complex inheritance patterns understandable.
Implementation (Interactive Demo)
\"use client\"\n\nimport { useState } from 'react';\n\nclass CounterLogic {\n #count = 0;\n increment() { this.#count++; return this.#count; }\n}\n\nexport default function ClassDemo() {\n const [count, setCount] = useState(0);\n const [counterInstance] = useState(new CounterLogic());\n\n const handleAdd = () => {\n setCount(counterInstance.increment());\n };\n\n return (\n <div className=\"p-4 flex flex-col gap-4\">\n <button onClick={handleAdd} className=\"bg-purple-500 text-white p-2 text-xl\">Clicked: {count} times</button>\n <p className=\"italic\">The #count variable is hidden inside the instance!</p>\n </div>\n );\n}This demo showcases how modern Class syntax combines the efficiency of prototypes with the security of private fields.
Common Mistakes/FAQ
Q1. Should I use arrow functions for class methods?
Methods defined with arrow functions inside a constructor are not placed on the prototype. They are created on every instance, losing memory efficiency. Use normal method syntax for shared logic.
Q2. Is Class just a prettier Prototype?
Mostly yes, but Class comes with stricter rules (e.g., must be called with new, methods are not enumerable) that help prevent common bugs.
Summary
- Use Prototype to share methods and save memory.
- Use IIFE to hide private data and encapsulate scope.
- Use ES6 Class as a robust framework for managing both patterns.
Conclusion
Understanding the relationship between Prototypes and Classes is key to mastering JavaScript's memory model. By combining these with IIFEs for privacy, you can build scalable and secure applications.