W3docs

El operador new de JavaScript

Aprende cómo los constructores y el operador new crean objetos en JavaScript: qué hace new paso a paso, la regla de retorno, new.target y convenciones de nombres.

Introducción a los constructores y el operador new

En JavaScript, los constructores son funciones diseñadas para inicializar objetos recién creados. Desempeñan un papel fundamental en la programación orientada a objetos al permitir a los desarrolladores definir las propiedades y comportamientos que deben tener los objetos de una determinada clase. El operador new se utiliza para crear una instancia de un objeto basada en una función constructora, configurando un entorno de object fresco a partir del prototipo especificado y ejecutando el constructor para inicializar el nuevo object.

Cómo funcionan los constructores

Una función constructora en JavaScript se parece a cualquier otra función, pero por convención se nombra con una letra mayúscula para distinguirla de las funciones normales. Cuando el operador new invoca una función constructora, ocurren cuatro cosas entre bastidores, equivalentes aproximadamente a este pseudocódigo:

function User(name) {
  // this = {};  (1) an empty object is created and assigned to this
  // this.__proto__ = User.prototype;  (2) prototype is linked

  this.name = name;  // (3) the constructor body runs, adding properties to this

  // return this;  (4) this is returned automatically
}
  1. Se crea un nuevo object vacío y se asigna a this.
  2. El prototipo se vincula: el [[Prototype]] interno del nuevo object se establece en la propiedad prototype del constructor, por lo que hereda las propiedades y métodos definidos allí.
  3. El cuerpo del constructor se ejecuta: la función se ejecuta con los argumentos que se le pasan, y this hace referencia al nuevo object recién creado, por lo que asignaciones como this.name = name le añaden propiedades.
  4. El object es devuelto: this se devuelve automáticamente a menos que el constructor devuelva explícitamente un object diferente (ver La regla del valor de retorno más abajo).
Información

El JavaScript moderno utiliza la sintaxis class para definir constructores y métodos de forma más intuitiva. Esto proporciona un enfoque más claro y basado en clases, similar al de otros lenguajes de programación.

Ejemplo: Función constructora básica

javascript— editable

Explicación: En este ejemplo, User es una función constructora que inicializa name, age y un método greet en los objetos recién creados. La sentencia new User('John', 30) crea una nueva instancia de User con el nombre "John" y la edad 30. Dentro de greet, this hace referencia al object sobre el que se llamó al método.

La regla del valor de retorno

Los constructores normalmente no usan return — el nuevo object (this) se devuelve automáticamente. Sin embargo, return tiene un comportamiento especial y fácil de pasar por alto dentro de un constructor:

  • Si return va seguido de un object, ese object se devuelve en lugar de this.
  • Si return va seguido de un primitivo (string, número, boolean, undefined, etc.), se ignora y this se devuelve como de costumbre.
javascript— editable

Explicación: WithObject devuelve un object plano, por lo que ese object reemplaza completamente a la instancia. WithPrimitive devuelve un string, que se ignora, por lo que se devuelve el this original (con name: 'Alice'). Rara vez dependerás de esto, pero explica resultados sorprendentes cuando un constructor devuelve accidentalmente un valor.

Detectar new con new.target

Dentro de cualquier función, new.target es undefined cuando la función se llama normalmente, y es igual a la función misma cuando se llama con new. Esto permite a un constructor detectar cómo fue invocado — útil para exigir (o permitir silenciosamente) el uso de la palabra clave new.

javascript— editable

Explicación: Dado que Modal comprueba new.target, llamar a Modal('Without new') sin new se redirige de forma transparente a new Modal(...), por lo que b sigue siendo una instancia real de Modal. (Nota: muchos equipos prefieren no hacer esto y dejar que la falta de new falle de forma clara.)

¿Cuándo usaría un constructor?

Usa una función constructora (o una clase) cuando necesites crear muchos objetos de la misma forma — múltiples usuarios, coches, widgets del DOM, etc. El constructor centraliza la lógica de configuración para que cada instancia se construya de la misma manera y comparta métodos a través del prototipo.

Si solo necesitas un objeto único, un object literal simple { ... } es más sencillo. Para un object de uso único que aún se beneficia del cuerpo de un constructor, puedes incluso usar un constructor anónimo:

javascript— editable

Explicación: La function anónima se ejecuta una sola vez como constructor y no se guarda en ningún lugar, por lo que no se puede reutilizar — es simplemente una forma de encapsular una configuración compleja de una sola vez.

Funciones constructoras vs. clases

El código moderno suele preferir la sintaxis class, que es esencialmente azúcar sintáctico sobre las funciones constructoras y los prototipos. Los dos fragmentos a continuación son equivalentes:

javascript— editable

Las clases añaden beneficios reales sobre las funciones constructoras: los métodos no son enumerables por defecto, el cuerpo se ejecuta en modo estricto, llamar a una clase sin new lanza un error, y extends/super hacen que la herencia sea mucho más limpia. Las funciones constructoras siguen siendo importantes de entender porque las clases están construidas sobre el mismo mecanismo de prototipo, y aún las encontrarás en código más antiguo.

Uso de constructores para objetos complejos

Los constructores se pueden usar para establecer relaciones más complejas entre objetos, incluyendo métodos que interactúan con otras propiedades de los objetos.

Ejemplo: Constructor con métodos

javascript— editable

Explicación: El constructor Car configura cada objeto de tipo coche con propiedades específicas y un método que muestra información sobre el coche.

Ejemplo: Métodos de prototipo

javascript— editable

Explicación: Al añadir introduce al prototipo de Employee, todas las instancias comparten el mismo método, lo que es más eficiente en memoria que definirlo directamente en el constructor.

Advertencia

Se recomienda usar las clases de ES6 para definir objetos y constructores para un código más limpio y legible.

Buenas prácticas con constructores

Al trabajar con constructores en JavaScript, seguir ciertas buenas prácticas puede mejorar considerablemente la legibilidad, eficiencia y escalabilidad del código. A continuación se describen las prácticas con ejemplos detallados y explicaciones:

1. Convención de nombres

Buena práctica: Siempre comienza los nombres de los constructores con una letra mayúscula para diferenciarlos de las funciones normales. Esta es una convención común en JavaScript y en muchos otros lenguajes de programación que ayuda a los desarrolladores a identificar rápidamente las funciones constructoras.

Ejemplo:

javascript— editable

Explicación: La función constructora Laptop comienza con una letra mayúscula, lo que indica que está pensada para usarse con el operador new para crear nuevos objetos.

2. Separar la lógica

Buena práctica: Para los métodos que no requieren acceso a los datos individuales de la instancia, defínelos en el prototipo del constructor en lugar de dentro del constructor. Este enfoque ahorra memoria porque todas las instancias comparten el mismo método en lugar de que cada instancia cree una nueva función en memoria.

Ejemplo:

javascript— editable

Explicación: El método describe se añade al prototipo de Book, lo que significa que todas las instancias de Book comparten el mismo método describe. Esto es más eficiente que si describe estuviera definido dentro del constructor, lo que crearía una nueva función para cada instancia del libro.

3. Valores de retorno

Buena práctica: Evita devolver valores desde los constructores. Los constructores de JavaScript devuelven automáticamente la nueva instancia del object a menos que se devuelva explícitamente un object diferente. Devolver valores que no sean objetos (como un string o un número) no tendrá efecto, y se devolverá igualmente la nueva instancia.

Ejemplo:

javascript— editable

Explicación: A pesar de intentar devolver un string desde el constructor Player, JavaScript ignora este valor de retorno porque no es un object. La nueva instancia de Player se devuelve como se esperaba.

Conclusión

Entender y utilizar los constructores y el operador new en JavaScript es fundamental para una programación orientada a objetos eficaz. Siguiendo las convenciones y buenas prácticas descritas aquí, los desarrolladores pueden crear código organizado, eficiente y escalable. Los constructores proporcionan un mecanismo poderoso para inicializar nuevos objetos y definir su comportamiento de manera estructurada e intuitiva.

Para profundizar, explora cómo los constructores comparten comportamiento a través de la herencia prototípica, cómo la sintaxis class se basa en estas ideas, y cómo una función es también un object con sus propias propiedades.

Práctica

Práctica
¿Qué ocurre cuando se ejecuta una función con 'new' en JavaScript?
¿Qué ocurre cuando se ejecuta una función con 'new' en JavaScript?
Was this page helpful?