IronWoods.es

Desarrollo web

Blog / JavaScript / Programación orientada a objetos en JavaScript

Se pueden usar clases y objetos en JavaScript para hacer el código más modular y mantenible, encapsulando comportamientos y características.

Carga de clases

He usado dos métodos para cargar clases en un proyecto, el primero no tiene (actualmente) problemas con las CORS, no requiere un servidor corriendo en segundo plano, etc. solo tus ficheros JS y HTML. El segundo más moderno, viene de ES6 y recuerda al uso de clases en frameworks actuales, requiere ese servidor y puede tener problemas de compatibilidad con navegadores antiguos.

Con el primer método los ficheros con las clases se cargan en cada fichero HTML donde se van a usar, en el segundo se cargan las clases en el script que las usa, lo que en general, simplifica su gestión.

Voy a plantear un ejemplo sencillo para cada método.

En cuanto a la organización de código, en ambos casos separo los scripts por features, dentro de una feature tengo el script principal en un fichero JS con el nombre de la feature en minúscula, una carpeta "classes" y dentro, un fichero para cada clase con su nombre empezando por mayúscula. Si tengo funciones de uso habitual, que pueden ser llamados en diversas features dentro o fuera de las clases, suelo incluirlos en "js/common/" en diferentes ficheros por funcionalidad, p.e. "js/common/dom.js" o "js/common/strings.js".

Usaré un documento HTML que llamaré "index.html" y el script principal estará en "src/js/app.js". El Script usa las clases 'UserActions' y 'User' que se encuentran en los ficheros "src/js/classes/UserActions.js" y "src/js/classes/User.js", respectivamente. Para los ejemplos no implemento features concretas.

Método 1 para la carga de clases

Lo importante es que los ficheros con las clases estén cargados antes de ser instanciadas o utilizadas (ocasionalmente el objecto puede instanciarse en el mismo fichero en que se define la clase). Entonces el documento "index.html" tiene este contenido:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Javascipt - POO</title>

    <script defer src="./src/js/user.js"></script>
    <script defer src="./src/js/Actions.js"></script>
    <script defer src="./src/js/app.js"></script>
</head>
<body>
    <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cumque dicta dolore,
        aliquam, quisquam tempore hic temporibus dolorum rerum reiciendis, deleniti
        repellat? Distinctio reiciendis quibusdam labore omnis quisquam corrupti ipsa accusantium.</p>
</body>
</html>

El fichero "src/js/app.js" contiene:


    console.warn('Creating a user...');

    let user = new User('Foo');
    const userActions = new UserActions(user);
    userActions.showName(); // Foo
    user = userActions.rename('Baz');
    userActions.showName(); // Baz
    console.log(user.name); // Baz

"src/js/classes/User.js" contiene:


    class User // class
    {

        constructor(name = 'Foo') // constructor
        {
            this.name = name;
        }
    }

"src/js/classes/UserActions.js" contiene:


    class UserActions // class
    {

        constructor(user) // constructor
        {
            this.user = user;
        }

        rename(newName) // user
        {
            this.user.name = newName;

            return this.user;
        }

        showName() // void
        {
            console.log(this.user.name);
        }
    }
Método 2 para la carga de clases

Sólo cargaré el script principal, este llama internamente a las clases que necesita. El documento "index.html" tiene este contenido:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Javascipt - POO</title>

    <script defer src="./src/js/app.js" type="module"></script>
</head>
<body>
    <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cumque dicta dolore,
        aliquam, quisquam tempore hic temporibus dolorum rerum reiciendis, deleniti
        repellat? Distinctio reiciendis quibusdam labore omnis quisquam corrupti ipsa accusantium.</p>
</body>
</html>

NOTA: es importante ver que en la etiqueta 'script' se incluye el atributo 'type="module"'.

El fichero "src/js/app.js" en este caso incluye al inicio sentencias para importar las clases y queda así:


    import User from './classes/User.js';
    import UserActions from './classes/UserActions.js';

    console.warn('Creating a Foo...');

    let user = new User('Foo');
    const userActions = new UserActions(user);
    userActions.showName(); // Foo
    user = userActions.rename('Baz');
    userActions.showName(); // Baz
    console.log(user.name); // Baz

Las clases serán las mismas, solo si incluye un export default en su cabecera:

"src/js/classes/User.js" contiene:


    export default class User // class
    {
        ...
    }

"src/js/classes/UserActions.js" contiene:


    export default class UserActions // class
    {
        ...
    }