Introducción
JavaScript es un lenguaje basado en prototipos, y cada objeto en JavaScript tiene una propiedad interna oculta llamada ]
que se puede usar para extender propiedades y métodos de objetos. Puede leer más sobre prototipos en nuestro tutorial entender prototipos y herencia en JavaScript.
hasta hace poco, los desarrolladores industriales usaban funciones de constructor para imitar un patrón de diseño orientado a objetos en JavaScript., La especificación de lenguaje ECMAScript 2015, a menudo conocida como ES6, introdujo clases al lenguaje JavaScript. Las clases en JavaScript en realidad no ofrecen funcionalidad adicional, y a menudo se describen como proporcionar «azúcar sintáctica» sobre prototipos y herencia en que ofrecen una sintaxis más limpia y elegante. Debido a que otros lenguajes de programación usan clases, la sintaxis de clases en JavaScript hace que sea más sencillo para los desarrolladores moverse entre idiomas.
las clases son funciones
Una clase 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 expressionconst x = function() {}
// Initializing a class with a class expressionconst y = class {}
podemos acceder a el ]
de un objeto utilizando la etiqueta Object.getPrototypeOf()
método. Usemos eso para probar la función vacía que creamos.
Object.getPrototypeOf(x);
Outputƒ () { }
también podemos usar ese método en la clase que hemos creado.,
Object.getPrototypeOf(y);
Outputƒ () { }
El código que se declara con la etiqueta function
y class
tanto el retorno de una función ]
. Con prototipos, cualquier función puede convertirse en una instancia de constructor usando la palabra clave new
.
Outputx {}constructor: ƒ ()
Esto se aplica a las clases.
Outputy {}constructor: class
estos ejemplos de constructores de prototipos están vacíos, pero podemos ver cómo debajo de la sintaxis, ambos métodos están logrando el mismo resultado final.,
definir una clase
en el tutorial prototipos y herencia, creamos un ejemplo basado en la creación de personajes en un juego de rol basado en texto. Continuemos con ese ejemplo aquí para actualizar la sintaxis de funciones a clases.
una función constructora se inicializa con un número de parámetros, que se asignarían como propiedades de this
, refiriéndose a la función en sí. La primera letra del identificador se escribiría en mayúscula por convención.
// Initializing a constructor functionfunction Hero(name, level) { this.name = name; this.level = level;}
cuando traducimos esto a la sintaxis de la clase, que se muestra a continuación, vemos que está estructurada de manera muy similar.
sabemos que una función constructora está destinada a ser un blueprint de objeto por la mayúscula de la primera letra del inicializador (que es opcional) y a través de la familiaridad con la sintaxis. La palabra clave class
comunica de una manera más directa El objetivo de nuestra función.,
la única diferencia en la sintaxis de la inicialización es usar la palabra clave class
en lugar de function
, y asignar las propiedades dentro de un método constructor()
.
definir métodos
la práctica común con las funciones constructoras es asignar métodos directamente al métodoprototype
en lugar de en la inicialización, como se ve en el métodogreet()
a continuación.
con clases esta sintaxis se simplifica, y el método se puede agregar directamente a la clase., Usando la abreviatura de definición de método introducida en ES6, definir un método es un proceso aún más conciso.
echemos un vistazo a estas propiedades y métodos en acción. Crearemos una nueva instancia de Hero
usando la palabra clave new
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.,
OutputHero {name: "Varg", level: 1}__proto__: ▶ constructor: class Hero ▶ greet: ƒ greet()
podemos ver en la salida que el constructor()
y greet()
funciones se aplica a la etiqueta __proto__
o ]
de hero1
, y no directamente como un método en el hero1
objeto. Si bien esto está claro al hacer funciones de constructor, no es obvio al crear clases. Las clases permiten una sintaxis más simple y sucinta, pero sacrifican algo de claridad en el proceso.,
extender una clase
Una característica ventajosa de las funciones y clases constructoras es que se pueden extender a nuevos blueprints de objetos basados en el padre. Esto evita la repetición de código para objetos que son similares pero necesitan algunas características adicionales o más específicas.
Se pueden crear nuevas funciones constructoras desde el padre usando el método call()
., En el ejemplo a continuación, crearemos una clase de caracteres más específica llamada Mage
, y asignaremos las propiedades de Hero
a ella usando call()
, además de agregar una propiedad adicional.
En este punto, podemos crear una nueva instancia de Mage
utilizando las mismas propiedades como Hero
así como uno nuevo que hemos añadido.,
const hero2 = new Mage('Lejon', 2, 'Magic Missile');
Envío hero2
en la consola, podemos ver que hemos creado un nuevo Mage
basada en el constructor.
OutputMage {name: "Lejon", level: 2, spell: "Magic Missile"}__proto__: ▶ constructor: ƒ Mage(name, level, spell)
Con ES6 clases, el super
palabra clave se utiliza en lugar de call
para acceder a las funciones de padres. Usaremos extends
para referirnos a la clase padre.
ahora podemos crear una nueva instancia Mage
de la misma manera.,
const hero2 = new Mage('Lejon', 2, 'Magic Missile');
vamos a imprimir hero2
a la consola y ver el resultado.
OutputMage {name: "Lejon", level: 2, spell: "Magic Missile"}__proto__: Hero ▶ constructor: class Mage
la salida es casi exactamente la misma, excepto que en la construcción de la clase el ]
está vinculado al Padre, en este caso Hero
.
a continuación se muestra una comparación lado a lado de todo el proceso de inicialización, adición de métodos y herencia de una función constructora y una clase.
aunque la sintaxis es bastante diferente, el resultado subyacente es casi el mismo entre ambos métodos. Las clases nos dan una forma más concisa de crear planos de objetos, y las funciones constructoras describen con mayor precisión lo que está sucediendo debajo del capó.
conclusión
en este tutorial, aprendimos sobre las similitudes y diferencias entre las funciones del constructor JavaScript y las clases ES6. Tanto las clases como Los Constructores imitan un modelo de herencia orientado a objetos a JavaScript, que es un lenguaje de herencia basado en prototipos.,
entender la herencia prototípica es primordial para ser un desarrollador JavaScript efectivo. Estar familiarizado con las clases es extremadamente útil, ya que las bibliotecas JavaScript populares como React hacen uso frecuente de la sintaxis class
.