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
- Declaración: Dentro de IIFE, objetos, closures o clases.
- Uso: Dentro del ámbito definido, las funciones encapsuladas pueden interactuar con elementos HTML y modificar estilos CSS dinámicamente.
- 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.
// escapeTool.js
const escapeTool = ( function () {
// Función para escapar HTML
function escapeHTML ( str ) {
return str
. replace ( /&/g , "&" )
. replace ( /</g , "<" )
. replace ( />/g , ">" )
. replace ( /"/g , """ )
. replace ( /'/g , "'" );
}
// 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/
.
<!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óninitialize
. - 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 aescapeTool.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
< 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
* {
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
<!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
ystyles.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.