Cómo usar clases en JavaScript

1 mar 2021 5 min di lettura
Cómo usar clases en JavaScript
Indice dei contenuti

Introducción

JavaScript es un lenguaje basado en prototipos, y cada objeto en JavaScript tiene una propiedad interna oculta llamada [[Prototype]] que se puede utilizar para ampliar las propiedades y métodos de los objetos.

La especificación del lenguaje ECMAScript 2015, a menudo denominada ES6, introdujo clases en el lenguaje JavaScript. Las clases en JavaScript en realidad no ofrecen ninguna funcionalidad adicional y a menudo se describen como "azúcar sintáctico" sobre los prototipos y la herencia, ya que ofrecen una sintaxis más limpia y elegante. Dado que otros lenguajes de programación usan clases, la sintaxis de clases en JavaScript facilita a los desarrolladores la navegación entre los distintos lenguajes.

Las clases son funciones

Una clase de JavaScript es un tipo de función. Las clases se declaran con la palabra clave class Usaremos la sintaxis de expresión de función para inicializar una función y la sintaxis de expresión de clase para inicializar una clase.

//Initializing a function with a function expression
 const x = function() {}
//Initializing a class with a class expression
 const y = class {}

Podemos acceder a [[Prototype]] de un objeto usando el método Object.getPrototypeOf() Usémoslo para probar la función vacía que tenemos.

Object.getPrototypeOf(x);
ƒ () { [native code] }

También podemos usar ese método en la clase que acabamos de crear.

Object.getPrototypeOf(y);
ƒ () { [native code] }

El código declarado con function y class devuelve una función [[Prototype]]. Con los prototipos, cualquier función puede convertirse en una instancia del constructor utilizando la new palabra clave.

const x = function() {}

 //Initialize a constructor from a function
 const constructorFromFunction = new x();

 console.log(constructorFromFunction);
x {}
 constructor: ƒ ()

Esto también se aplica a las clases.

const y = class {}

 //Initialize a constructor from a class
 const constructorFromClass = new y();

 console.log(constructorFromClass);
y {}
 constructor: class

Estos ejemplos de constructores de prototipos están vacíos, pero podemos ver la sintaxis, ambos métodos obtienen el mismo resultado final.

Definir una clase

Una función constructora se inicializa con una serie de parámetros, que serían asignados como propiedades de this, haciendo referencia a la propia función. La primera letra del identificador estaría en mayúscula por convención.

//Initializing a constructor function
 function Hero(name, level) {
 this.name = name;
 this.level = level;
 }
constructor.js

Cuando lo traducimos a la sintaxis de la clase, que se muestra a continuación, vemos que está estructurado de manera muy similar.

//Initializing a class definition
 class Hero {
 constructor(name, level) {
 this.name = name;
 this.level = level;
 }
 }
class.js

Sabemos que una función de constructor está destinada a ser un modelo de objeto con la primera letra del inicializador en mayúscula (que es opcional). class palabra clave comunica más directamente el propósito de nuestra función.

La única diferencia en la sintaxis de inicialización es usar la palabra clave de class function asignar propiedades dentro de un método constructor()

Definir los métodos

La práctica común con las funciones de constructores es asignar métodos directamente al prototype lugar de la inicialización, como se ve en el siguiente método greet()

function Hero(name, level) {
 this.name = name;
 this.level = level;
 }

 //Adding a method to the constructor
 Hero.prototype.greet = function() {
 return `${this.name} says hello.`;
 }
constructor.js

Con las clases, esta sintaxis se simplifica y el método se puede agregar directamente a la clase. Usando el atajo de definición de método introducido en ES6, definir un método es un proceso aún más conciso.

class Hero {
 constructor(name, level) {
 this.name = name;
 this.level = level;
 }

 //Adding a method to the constructor
 greet() {
 return `${this.name} says hello.`;
 }
 }
class.js

Echemos un vistazo a estas propiedades y métodos en acción. Crearemos una nueva instancia de Hero new palabra clave y asignaremos algunos valores.

const hero1 = new Hero('Varg', 1);

Si imprimimos más información sobre nuestro nuevo objeto con console.log(hero1), podemos ver más detalles sobre lo que está sucediendo con la inicialización de la clase.

Hero {name: "Varg", level: 1}
 __proto__:
 ▶ constructor: class Hero
 ▶ greet: ƒ greet()

Podemos ver en la salida que las funciones constructor() y greet() se han aplicado a __proto__, o [[Prototype]] de hero1, y no directamente como un método en hero1. Si bien esto es claro cuando se crean funciones de constructores, no es obvio cuando se crean clases. Las clases permiten una sintaxis más simple y concisa, pero sacrifican algo de claridad en el proceso.

Ampliar una clase

Una característica ventajosa de las funciones y clases de constructor es que pueden extenderse a nuevos esquemas de objetos basados en padres. Esto evita la repetición de código para objetos que son similares pero requieren alguna funcionalidad adicional o más específica.

El padre puede crear nuevas funciones de constructor utilizando el método call() En el siguiente ejemplo, crearemos una clase de personaje más específica llamada Mage y le asignaremos propiedades de Hero call(), además de agregar una propiedad adicional.

//Creating a new constructor from the parent
 function Mage(name, level, spell) {
 //Chain constructor with call
 Hero.call(this, name, level);

 this.spell = spell;
 }
constructor.js

En este punto, podemos crear una nueva instancia de Mage usando las mismas propiedades que Hero y una nueva adición.

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

Al iniciar hero2 desde la consola, podemos ver que hemos creado un nuevo Mage

Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
 __proto__:
 ▶ constructor: ƒ Mage(name, level, spell)

Con las clases de ES6, la super se usa en lugar de la call para acceder a las funciones principales. Usaremos extends para referirnos a la clase principal (parent).

//Creating a new class from the parent
 class Mage extends Hero {
 constructor(name, level, spell) {
 //Chain constructor with super
 super(name, level);

 //Add a new property
 this.spell = spell;
 }
 }
class.js

Ahora podemos crear una nueva Mage de la misma manera.

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

Imprimiremos hero2 en la consola y veremos el resultado.

Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
 __proto__: Hero
 ▶ constructor: class Mage

El resultado es casi exactamente el mismo, excepto que en el constructor de la [[Prototype]] está vinculado al padre, en este caso Hero.

A continuación se muestra una comparación en paralelo de todo el proceso de inicialización, adición de métodos y herencia de una función de constructor y una clase.

function Hero(name, level) {
 this.name = name;
 this.level = level;
 }

 //Adding a method to the constructor
 Hero.prototype.greet = function() {
 return `${this.name} says hello.`;
 }

 //Creating a new constructor from the parent
 function Mage(name, level, spell) {
 //Chain constructor with call
 Hero.call(this, name, level);

 this.spell = spell;
 }
constructor.js
//Initializing a class
 class Hero {
 constructor(name, level) {
 this.name = name;
 this.level = level;
 }

 //Adding a method to the constructor
 greet() {
 return `${this.name} says hello.`;
 }
 }

 //Creating a new class from the parent
 class Mage extends Hero {
 constructor(name, level, spell) {
 //Chain constructor with super
 super(name, level);

 //Add a new property
 this.spell = spell;
 }
 }
class.js

Aunque la sintaxis es bastante diferente, el resultado subyacente es casi el mismo entre ambos métodos. Las clases nos brindan una forma más concisa de crear planos de objetos y las funciones de los constructores describen con mayor precisión lo que está sucediendo.

Conclusión

En este tutorial, aprendimos sobre las similitudes y diferencias entre las funciones del constructor de JavaScript y las clases de ES6. Tanto las clases como los constructores imitan un modelo de herencia orientado a objetos en JavaScript, que es un lenguaje de herencia basado en prototipos.

Comprender la herencia prototípica es fundamental para ser un desarrollador de JavaScript eficaz. Conocer las clases es extremadamente útil, ya que las bibliotecas populares de JavaScript como React hacen un uso frecuente de la sintaxis class

Buy me a coffeeBuy me a coffee

Supportaci se ti piacciono i nostri contenuti. Grazie.

Successivamente, completa il checkout per l'accesso completo a Noviello.it.
Bentornato! Accesso eseguito correttamente.
Ti sei abbonato con successo a Noviello.it.
Successo! Il tuo account è completamente attivato, ora hai accesso a tutti i contenuti.
Operazione riuscita. Le tue informazioni di fatturazione sono state aggiornate.
La tua fatturazione non è stata aggiornata.