Seleccionar página

clases o funciones

Para poder definir clases tenemos básicamente dos opciones, utilizar class o utilizar function. Aunque puedan parecer muy diferentes, son completamente equivalentes, como vamos ir viendo en toda esta serie de artículos.

class function
class C {}

console.assert( typeof C === 'function' );
function C () {}

console.assert( typeof C === 'function' );

En ambos casos, el tipo es function. Esto puede sorprender un poco, ya que quizás se podría esperar que class fuera de otro tipo, quizás uno específico, pero ambos son funciones, funciones constructoras, es decir, que se espera que se utilicen con new.

Si analizamos estas funciones obtendremos esta información sobre la cadena de prototipos del constructor:

    prototipo

    Las funciones (y por lo tanto, también las clases) tienen una propiedad denominada prototype donde reside la información que es utilizada para crear los objetos. Todos los miembros del objeto prototype del constructor serán miembros del objeto una vez instanciado con new:

    class function
    class C {
      m1() {
      }
      m2() {
      }
    }
    
    const obj = new C();
    console.assert( typeof obj.m1 === 'function' );
    console.assert( typeof obj.m2 === 'function' );
    
    function C () {
    }
    C.prototype = {
      m1: function() {
      },
      m2: function() {
      }
    };
    
    const obj = new C();
    console.assert( typeof obj.m1 === 'function' );
    console.assert( typeof obj.m2 === 'function' );
    

    Si exploramos el objeto obj y el prototipo C.prototype comprobaremos que ambos tiene los mismos miembros:


        Es interesante saber que si modificamos dinámicamente el prototipo de una clase, estamos cambiando todos los objetos creados a partir de ella, ya los miembros de C.prototype no se copian, si no que se hacen referencia al mismo dentro de obj.__proto__ (más adelante veremos que es y cómo funciona esta extraña propiedad llamada __proto__.

        hoisting

        class function
        try {
          
          const obj = new C();
          
          console.assert( false );
        } catch (err) {
          console.assert( err.message === 'C is not defined' );
        }
        
        class C {
        }
        
        const obj = new C();
        
        function C () {
        }
        

        Las funciones pueden ser llamadas en el código antes de su definición, esto es así por medio del proceso de hoisting que se produce en la compilación del Javascript.

        Esto no ocurre con las clases, que deben ser siempre declaradas en el código antes de su uso. Debemos tenerlo en cuenta para evitar errores.

        alcance

        class function
        {
          class C {
          }
        }
        
        try {
          const obj = new C();
          console.assert( false );
        } catch (err) {
          console.assert( 
            err.message === 'C is not defined' 
          );
        }
        
        function x () {
          function C () {
          }
        }
        
        try {
          const obj = new C();
          console.assert( false );
        } catch (err) {
          console.assert(
            err.message === 'C is not defined'
          );
        }
        

        Como la mayoría de los elementos definidos en Javascript, estos tiene un alcance o ámbito definido. class tiene el alcance comprendido por llaves, de forma similar a las variables creadas con let. Por su parte function es local la función donde ha sido definida. No podemos, por lo tanto, utilizar una clase o una función constructora fuera del alcance donde se encuentra.

        expresión anónima

        class function
        const C = class {};
        
        console.assert( typeof  C === 'function' );
        
        const C = function () {};
        
        console.assert( typeof C === 'function' );
        

        Tanto las funciones como las clases pueden ser utilizadas como expresiones y, por lo tanto, pueden ser definidas de forma anónima, es decir, sin aplicarles un nombre concreto. Las clases y las funciones pueden almacenarse en variables, pasarse como parámetros o retornarse desde funciones. Son, por lo tanto, miembros de primer orden del lenguaje.

        Si una clase o una función es asignada a una variable o pasada como parámetro, no se produce una copia de la misma, como todos los objetos de Javascript (recordemos que Function hereda de Object) es pasado por referencia y se mantiene una sola instancia referenciada por varias variables.

          Índice constructor