Tres formas de simular clases en JavaScript

1. El patrón Constructor

JavaScript no nació con paradigmas de orientación a objetos puros, pero permite simular clases mediante funciones constructoras. En este enfoque, se utiliza la palabra clave this para asignar propiedades al contexto del nuevo objeto.

function Felino() {
    this.alias = "Michi";
}

var mascota1 = new Felino();
console.log(mascota1.alias); // Michi

Los métodos pueden vincularse al prototipo de la función para optimizar la memoria, evitando duplicar la lógica en cada instancia.

Felino.prototype.emitirSonido = function() {
    console.log("Miau");
};

2. El método Object.create()

Introducido en ECMAScript 5, este mecanismo permite crear instancias directamente a partir de un objeto prototípico, sin necesidad de utiliazr new ni lidiar con la complejidad de this en la declaración inicial.

var Felino = {
    alias: "Michi",
    emitirSonido: function() { console.log("Miau"); }
};

var mascota1 = Object.create(Felino);
console.log(mascota1.alias); // Michi
mascota1.emitirSonido(); // Miau

Para entornos antigous que carecen de soporte nativo, se puede implementar un polyfill sencillo:

if (typeof Object.create !== 'function') {
    Object.create = function(proto) {
        function ConstructorIntermedio() {}
        ConstructorIntermedio.prototype = proto;
        return new ConstructorIntermedio();
    };
}

3. El enfoque de Fábrica Minimalista

Esta técnica evita por completo el uso de this y prototype, utilizando un objeto simple que contiene una función generadora. Al invocarla, se construye y retorna un nuevo objeto con sus propiedades y métodos.

var Felino = {
    generar: function() {
        var instancia = {};
        instancia.alias = "Michi";
        instancia.emitirSonido = function() { console.log("Miau"); };
        return instancia;
    }
};

var mascota1 = Felino.generar();
mascota1.emitirSonido(); // Miau

Herencia

Para que una clase herede de otra, basta con invocar el método generador de la clase base dentro del generador de la subclase.

var SerVivo = {
    generar: function() {
        var instancia = {};
        instancia.reposar = function() { console.log("Durmiendo"); };
        return instancia;
    }
};

var Felino = {
    generar: function() {
        var instancia = SerVivo.generar();
        instancia.alias = "Michi";
        instancia.emitirSonido = function() { console.log("Miau"); };
        return instancia;
    }
};

var mascota1 = Felino.generar();
mascota1.reposar(); // Durmiendo

Privacidad de variables

Las variables declaraads dentro del bloque de la función generadora, pero no adjuntadas al objeto de retorno, permanecen privadas gracias al cierre (closure) de la función.

var Felino = {
    generar: function() {
        var instancia = {};
        var secreto = "Miau";
        instancia.revelarSecreto = function() { console.log(secreto); };
        return instancia;
    }
};

var mascota1 = Felino.generar();
console.log(mascota1.secreto); // undefined

Datos compartidos

Si se necesita que todas las instancias accedan o modifiquen un mismo estado, este dato debe declararse en el objeto contenedor principal, fuera de la función generadora.

var Felino = {
    sonidoCompartido: "Miau",
    generar: function() {
        var instancia = {};
        instancia.escuchar = function() { console.log(Felino.sonidoCompartido); };
        instancia.actualizarSonido = function(nuevo) { Felino.sonidoCompartido = nuevo; };
        return instancia;
    }
};

var mascota1 = Felino.generar();
var mascota2 = Felino.generar();

mascota2.actualizarSonido("Prrr");
mascota1.escuchar(); // Prrr

Etiquetas: JavaScript ecmascript Prototipos closures Object.create

Publicado el 7-12 09:01