Encapsular funciones en JavaScript

 Encapsular funciones en JavaScript significa limitar su alcance, protegiendo su comportamiento y datos para que no sean directamente accesibles desde el exterior. Esto es útil para evitar conflictos de nombres, mejorar la modularidad y mantener el código limpio.  


 

1. Usando Funciones Anónimas Autoejecutables (IIFE)

Un patrón común para encapsulación es envolver el código en una IIFE (Immediately Invoked Function Expression). Esto crea un ámbito cerrado.

(function() {
 function funcionEncapsulada() {
  console.log("Esta función está encapsulada.");
 }

 // Llamar a la función dentro del alcance.
 funcionEncapsulada();
})();

// No se puede acceder fuera del bloque:
// console.log(funcionEncapsulada); // Error

 

2. Usando Objetos Literales

Se pueden encapsular funciones dentro de un objeto para agruparlas como métodos.

const modulo = {
 iniciar: function() {
  console.log("Módulo iniciado.");
 },
 detener: function() {
  console.log("Módulo detenido.");
 }
};

// Uso
modulo.iniciar();
modulo.detener();
 

 

3. Aprovechando Closures

Los closures te permiten encapsular variables y funciones, haciendo que solo sean accesibles a través de métodos internos.

function crearContador() {
 let contador = 0; // Variable encapsulada

 return {
  incrementar: function() {
   contador++;
   console.log(`Contador: ${contador}`);
  },
  reiniciar: function() {
   contador = 0;
   console.log("Contador reiniciado.");
  }
 };
}

const contador = crearContador();
contador.incrementar(); // Contador: 1
contador.incrementar(); // Contador: 2
contador.reiniciar();  // Contador reiniciado

 

4. Clases (ES6)

Las clases permiten encapsular métodos y datos dentro de instancias. Puedes usar campos privados con la convención de prefijo _ o con #.

 class Modulo {
 #datoPrivado = "Esto es privado"; // Campo privado

 iniciar() {
  console.log("Módulo iniciado.");
  console.log(this.#datoPrivado);
 }

 detener() {
  console.log("Módulo detenido.");
 }
}

const miModulo = new Modulo();
miModulo.iniciar(); // Accede a método público
// console.log(miModulo.#datoPrivado); // Error
 

 

5. Módulos de JavaScript (ES6)

Si usas el sistema de módulos con export e import, puedes exportar solo las partes públicas y encapsular el resto.

 // archivo.js
function funcionPrivada() {
 console.log("Esto es privado");
}

export function funcionPublica() {
 console.log("Esto es público");
 funcionPrivada();
}

// main.js
import { funcionPublica } from './archivo.js';
funcionPublica(); // Accede solo a lo público
 

 

El uso de funciones encapsuladas en JavaScript depende de cómo se hayan implementado y el objetivo del proyecto. Te explico todo en detalle:

¿Cómo se declaran y usan las funciones encapsuladas?

1- Declaración: Las funciones encapsuladas se declaran dentro de un ámbito restringido, como una función envolvente, un objeto, un closure o una clase. Aquí tienes ejemplos:

Dentro de una IIFE (Immediately Invoked Function Expression):

(function() {
  function funcionEncapsulada() {
    console.log("Esta es una función encapsulada.");
  }

  // Uso dentro del ámbito restringido
  funcionEncapsulada();
})();

// Fuera del IIFE, no se puede acceder:
// funcionEncapsulada(); // Error

Dentro de un Objeto:

const modulo = {
  iniciar: function() {
    console.log("Módulo iniciado.");
  },
  detener: function() {
    console.log("Módulo detenido.");
  }
};

// Uso
modulo.iniciar(); // Accede mediante el objeto

Dentro de un Closure:

function contador() {
  let valor = 0;
  return {
    incrementar: function() {
      valor++;
      console.log(`Contador: ${valor}`);
    }
  };
}

const miContador = contador();
miContador.incrementar(); // Contador: 1

2-  Dónde se usan: Las funciones encapsuladas se utilizan dentro del ámbito donde se declaran. Puedes llamarlas desde otros métodos del mismo objeto o clase, pero no directamente desde fuera.

Relación con HTML y CSS

Las funciones encapsuladas tienen un rol importante en la interacción con HTML y CSS porque permiten modularizar el comportamiento dinámico que afecta a la estructura y el estilo de las páginas web.

HTML: Las funciones encapsuladas pueden interactuar con elementos HTML utilizando JavaScript. Por ejemplo, puedes realizar cambios en el DOM desde dentro de una función encapsulada:

(function() {
  function cambiarTexto(id) {
    const elemento = document.getElementById(id);
    elemento.innerText = "Texto cambiado dinámicamente";
  }

  cambiarTexto('miElemento');
})();

HTML vinculado:

<div id="miElemento">Texto original</div>

CSS: Las funciones encapsuladas pueden modificar estilos dinámicamente usando la propiedad style del DOM o inyectando reglas CSS directamente:  

const moduloEstilo = (function() {
  function cambiarColor(id, color) {
    const elemento = document.getElementById(id);
    elemento.style.color = color;
  }

  return {
    aplicarColor: cambiarColor
  };
})();

// Uso
moduloEstilo.aplicarColor('miElemento', 'blue');

HTML vinculado:

<div id="miElemento">Texto con estilo dinámico</div>

 

Dónde implementar estas funciones

Estas funciones suelen implementarse en archivos .js y se vinculan al HTML mediante un <script> o módulos ES6. Aquí tienes un ejemplo de estructura completa:

HTML:

<button id="miBoton">Cambiar estilo</button>
<div id="miElemento">Contenido dinámico</div>
<script src="script.js"></script>

CSS:  

#miElemento {
  color: red;
}

JavaScript (script.js):

(function() {
  function cambiarEstilo() {
    const elemento = document.getElementById('miElemento');
    elemento.style.color = 'green';
    elemento.innerText = 'Estilo cambiado';
  }

  document.getElementById('miBoton').addEventListener('click', cambiarEstilo);
})();

 

Resumen

  1. Declaración: Dentro de IIFE, objetos, closures o clases.
  2.   Uso: Dentro del ámbito definido, las funciones encapsuladas pueden interactuar con elementos HTML y modificar estilos CSS dinámicamente.
  3. Vinculación: Las funciones encapsuladas se conectan al HTML/CSS a través de eventos y manipulaciones del DOM.

 

 

Encapsulación de un archivo

1. Encapsulación en un archivo JavaScript

Guarda todo el comportamiento de JavaScript en un archivo independiente llamado, por ejemplo, escapeTool.js. Encapsularemos las funciones y eventos en un módulo.

javascript
 // escapeTool.js 
 const  escapeTool = ( function  () {
   // Función para escapar HTML 
   function   escapeHTML ( str ) {
     return  str
      . replace ( /&/g ,  "&amp;" )
      . replace ( /</g ,  "&lt;" )
      . replace ( />/g ,  "&gt;" )
      . replace ( /"/g ,  "&quot;" )
      . replace ( /'/g ,  "&#39;" );
  }

   // Inicializador de eventos 
   function   initialize () {
     document . getElementById ( "escapeButton" ). addEventListener ( "click" ,  () =>  {
       const  inputText =  document . getElementById ( "inputText" ). value ;
       const  escapedText =  escapeHTML (inputText);
       document . getElementById ( "outputText" ). value  = escapedText;
    });

     document . getElementById ( "copy-btn" ). addEventListener ( "click" ,  () =>  {
       const  selection =
         document . getElementById ( "outputText" ). value  ||
         document . getElementById ( "div-content" ). innerText ;
      navigator. clipboard . writeText (selection). catch ( ( err ) =>  {
         alert ( "Error al copiar: "  + err);
      });
    });

     document . getElementById ( "paste-btn" ). addEventListener ( "click" ,  async  () => {
       try  {
         const  text =  await  navigator. clipboard . readText ();
         if  ( document . activeElement  ===  document . getElementById ( "outputText" )) {
           document . getElementById ( "outputText" ). value  = text;
        }  else  {
           document . getElementById ( "inputText" ). value  = text;
        }
      }  catch  (err) {
         alert ( "Error al pegar: "  + err);
      }
    });

     document . getElementById ( "detect-btn" ). addEventListener ( "click" ,  () =>  {
       const  content =
         document . getElementById ( "inputText" ). value  ||
         document . getElementById ( "div-content" ). innerText ;
       let  detectedLanguage =  "Desconocido" ;

       if  ( /function|var|let|const|console/ . test (content)) {
        detectedLanguage =  "JavaScript" ;
      }  else   if  ( /import|def|print/ . test (content)) {
        detectedLanguage =  "Python" ;
      }  else   if  ( /class|public|static/ . test (content)) {
        detectedLanguage =  "Java" ;
      }  else   if  ( /<!DOCTYPE html>|<div|<span/ . test (content)) {
        detectedLanguage =  "HTML" ;
      }

       document . getElementById ( "result" ). innerText  =  `Lenguaje detectado:  ${detectedLanguage} ` ;
    });
  }

   // Exporta la función de inicialización 
   return  {
    initialize,
  };
})();
 

2. Página web para usarlo

Ahora puedes crear una página web diferente que haga uso del archivo encapsulado escapeTool.js. Guárdalo en el mismo directorio o en un subdirectorio, como scripts/.

html
 <!DOCTYPE  html > 
 < html   lang = "en" > 
   < head > 
     < meta   charset = "UTF-8"  /> 
     < meta   name = "viewport"   content = "width=device-width, initial-scale=1.0"  /> 
     < title > Uso de escapeTool </ title > 
     < style >  
       body  {
         font-family : Arial, sans-serif;
         margin :  0 ;
         padding :  20px ;
         background-color :  #f4f4f9 ;
      }
      </ style > 
   </ head > 
   < body > 
     < div   class = "container" > 
       < h2 > Generador de Código de Escape HTML </ h2 > 
       < textarea   id = "inputText"   placeholder = "Ingresa tu texto aquí..." >  </ textarea > 
       < button   id = "escapeButton" > Convertir a Escape HTML </ button > 
       < textarea   id = "outputText"   readonly >  </ textarea > 
       < div > 
         < button   id = "copy-btn" > Copiar </ button > 
         < button   id = "paste-btn" > Pegar </ button > 
         < button   id = "detect-btn" > Detectar Lenguaje </ button > 
       </ div > 
       < div   id = "result" >  </ div > 
     </ div > 

     <!-- Importar el módulo desde otro directorio --> 
     < script   src = "scripts/escapeTool.js" >  </ script > 
     < script >  
       // Inicializar la funcionalidad encapsulada 
      escapeTool. initialize ();
      </ script > 
   </ body > 
 </ html > 
 

3. Estructura del proyecto

Asegúrate de organizar tu proyecto así:

 
proyecto/
│
├── index.html                <!-- Página principal -->
├── scripts/
│   └── escapeTool.js         <!-- Archivo encapsulado -->
└── styles/
    └── styles.css            <!-- Estilos globales opcionales -->
 

Cómo funciona esta estructura

  • Encapsulación: La funcionalidad está en escapeTool.js, dentro de un módulo que oculta sus funciones internas y exporta solo la función initialize.
  • Relación con HTML y CSS: El código JavaScript manipula el DOM del HTML y puede aplicar estilos dinámicamente al interactuar con los elementos.
  • Uso en otra página web: Importa el archivo escapeTool.js en cualquier página usando <script> y luego inicializa las funcionalidades llamando a escapeTool.initialize().

  Con esta estructura, puedes usar las funciones encapsuladas en múltiples páginas web sin duplicar el código.

 

Reutilizar codigo

Puedes reutilizar tanto el diseño estructurado (HTML) como los estilos (CSS) en múltiples páginas web para evitar tener que rediseñar y reestructurar el código. Esto se logra al externalizar el HTML y los estilos en un componente reutilizable y luego integrarlos dinámicamente en cualquier página web. Te explico cómo hacerlo:

1. Paso 1: Guardar el HTML estructurado como un archivo de plantilla

Extrae el código HTML principal (el contenido de <div class="container">) y guárdalo en un archivo separado, por ejemplo, template.html.

Archivo: template.html

html
 < div   class = "container" > 
   < div   class = "container-row" > 
     < div   class = "container-col" > 
       < h2   class = "titulo" > Generador de Código de Escape HTML </ h2 > 
       < div   class = "toolbar" > 
         < button   id = "paste-btn"   class = "btn" > Pegar </ button > 
         < button   id = "detect-btn"   class = "btn" > Detectar Lenguaje </ button > 
       </ div > 
       < textarea   id = "inputText"   class = "inputText"   placeholder = "Ingresa tu texto aquí..." >  </ textarea > 
       < button   id = "escapeButton"   class = "btn" > Convertir a Escape HTML </ button > 
     </ div > 
     < div   class = "container-col" > 
       < h2   class = "titulo" > Resultado: Código de Escape HTML </ h2 > 
       < div   class = "toolbar" > 
         < button   id = "copy-btn"   class = "btn" > Copiar </ button > 
       </ div > 
       < textarea   id = "outputText"   class = "outputText"   readonly >  </ textarea > 
       < br > 
       < h2   class = "titulo" > Resultado: Lenguaje </ h2 > 
       < div   class = "result"   id = "result" >  </ div > 
     </ div > 
   </ div > 
 </ div > 
 

2. Paso 2: Guardar los estilos CSS en un archivo independiente

Extrae el código CSS y guárdalo en un archivo llamado styles.css.

Archivo: styles.css

css
* {
   margin :  0px ;
   padding :  0px ;
   box-sizing : border-box;
   font-family :  "Lato" , sans-serif;
}
 body  {
   font-family : Arial, sans-serif;
   margin :  0 ;
   padding :  0 ;
   height :  100vh ;
   background-color :  #f4f4f9 ;
}
 .container  {
   background :  #ffffff ;
   padding :  20px ;
   border-radius :  10px ;
   box-shadow :  0   4px   8px   rgba ( 0 ,  0 ,  0 ,  0.1 );
   min-width :  300px ;
   width :  100% ;
   height :  100vh ;
   text-align : center;
}
 .container-row  {
   display : flex;
   background-color :  #f4f4f9 ;
}
 .container-col  {
   height :  95vh ;
   width :  90% ;
   background-color :  #f4f4f9 ;
}
 .titulo  {
   margin-top :  10px ;
   color :  #333 ;
}
 .toolbar  {
   display : flex;
   align-items : center;
   gap :  10px ;
   border-radius :  5px ;
}
 .toolbar   button  .btn  {
   background :  #0056b3 ;
   color :  #fff ;
   border : none;
   padding :  4px   10px ;
   cursor : pointer;
   border-radius :  4px ;
}
 .toolbar   button  .btn  :hover  {
   background :  #007bff ;
}
 textarea  .inputText ,  textarea  .outputText  {
   min-width :  400px ;
   width :  90% ;
   height :  200px ;
   margin :  5px   20px ;
   padding :  5px   20px ;
   border :  1px  solid  #ccc ;
   border-radius :  5px ;
   font-size :  15px ;
}
 .btn  {
   background-color :  #007bff ;
   color :  #fff ;
   border : none;
   padding :  10px   20px ;
   border-radius :  5px ;
   cursor : pointer;
   font-size :  16px ;
   font-weight :  600 ;
}
 .btn  :hover  {
   background-color :  #0056b3 ;
}
 .result  {
   margin-top :  10px ;
   color :  #333 ;
   font-weight : bold;
}
 

3. Paso 3: Usar JavaScript para cargar dinámicamente el diseño y los estilos

En tu página principal, usa JavaScript para cargar tanto el HTML de template.html como los estilos de styles.css.

Archivo principal: index.html

html
 <!DOCTYPE  html > 
 < html   lang = "en" > 
   < head > 
     < meta   charset = "UTF-8" > 
     < meta   name = "viewport"   content = "width=device-width, initial-scale=1.0" > 
     < title > Reutilizar Componentes </ title > 
   </ head > 
   < body > 
     <!-- Contenedor donde se cargará el HTML --> 
     < div   id = "app" >  </ div > 

     <!-- Carga dinámica de contenido --> 
     < script >  
       // Función para cargar dinámicamente un archivo HTML 
       async   function   loadTemplate ( url, containerId ) {
         const  response =  await   fetch (url);
         const  html =  await  response. text ();
         document . getElementById (containerId). innerHTML  = html;
      }

       // Inicia la carga del HTML y estilos 
       loadTemplate ( 'template.html' ,  'app' );
       const  link =  document . createElement ( 'link' );
      link. rel  =  'stylesheet' ;
      link. href  =  'styles.css' ;
       document . head . appendChild (link);
      </ script > 

     <!-- Importar escapeTool.js --> 
     < script   src = "escapeTool.js" >  </ script > 
     < script >  
       // Inicializar funcionalidades 
      escapeTool. initialize ();
      </ script > 
   </ body > 
 </ html > 
 

4. Estructura del proyecto

Organiza tus archivos en el proyecto de la siguiente forma:

 
proyecto/
│
├── index.html         <!-- Página principal -->
├── template.html      <!-- Diseño estructurado reutilizable -->
├── styles.css         <!-- Estilos reutilizables -->
├── escapeTool.js      <!-- Lógica encapsulada -->
 

Ventajas de este enfoque

  •   Reutilización: Puedes usar template.html y styles.css en múltiples páginas sin duplicar código.
  • Modularidad: El diseño (HTML), los estilos (CSS) y la funcionalidad (JS) están separados, lo que facilita su mantenimiento.
  • Mantenimiento: Si necesitas actualizar el diseño o los estilos, solo actualizas los archivos compartidos.

 

Artículo Anterior Artículo Siguiente