JavaScript no es un lenguaje orientado a objetos basado en clases. Pero todavía tiene formas de usar la programación orientada a objetos (OOP).
En este tutorial, explicaré OOP y te mostraré cómo usarlo.
De acuerdo con Wikipedia, la programación basada en clases es
un estilo de programación orientada a objetos (OOP) en el que la herencia se produce a través de la definición de clases de objetos, en lugar de la herencia que se produce a través de los objetos solos
El modelo más popular de OOP está basado en clases.
Pero como he mencionado, JavaScript no es un lenguaje basado en clases, es un lenguaje basado en prototipos.
Según la documentación de Mozilla:
Un lenguaje basado en prototipos tiene la noción de un objeto prototípico, un objeto que se usa como plantilla para obtener las propiedades iniciales de un nuevo objeto.
echa un vistazo a este código:
let names = { fname: "Dillion", lname: "Megida"}console.log(names.fname);console.log(names.hasOwnProperty("mname"));// Expected Output// Dillion// false
La variable de objeto names
sólo tiene dos propiedades – fname
y lname
. Ningún método en absoluto.
Entonces, ¿de dónde viene hasOwnProperty
?
Bueno, proviene del prototipo Object
.
Trate de registro el contenido de la variable a la consola:
console.log(names);
Cuando usted ampliar los resultados en la consola, vas a conseguir esto:
Observe la última propiedad – __proto__
? Trate de ampliar ella:
verás un conjunto de propiedades en el Object
constructor. Todas estas propiedades provienen del prototipo global Object
. Si miras de cerca, también notarás nuestro hasOwnProperty
oculto .
En otras palabras, todos los objetos tienen acceso al prototipo de Object
. No poseen estas propiedades, pero se les concede acceso a las propiedades del prototipo.
La propiedad _ _ proto _ _
Apunta al objeto que se utiliza como prototipo.
Esta es la propiedad de cada objeto que le da acceso a la propiedad Object prototype
.
Cada objeto tiene esta propiedad de forma predeterminada, que se refiere al Object Protoype
excepto cuando se configura de otra manera (es decir, cuando el __proto__
del objeto apunta a otro prototipo).
Modificar la propiedad __proto__
Esta propiedad se puede modificar indicando explícitamente que debe referirse a otro prototipo. Para ello se utilizan los siguientes métodos:
Objeto.crear()
function DogObject(name, age) { let dog = Object.create(constructorObject); dog.name = name; dog.age = age; return dog;}let constructorObject = { speak: function(){ return "I am a dog" }}let bingo = DogObject("Bingo", 54);console.log(bingo);
En la consola, esto es lo que tendrías:
Observe la propiedad __proto__
y el método speak
?
Object.create
utiliza el argumento que se le pasa para convertirse en el prototipo.
palabra clave
function DogObject(name, age) { this.name = name; this.age = age;}DogObject.prototype.speak = function() { return "I am a dog";}let john = new DogObject("John", 45);
john
‘s __proto__
propiedad está dirigido a DogObject
‘s prototipo. Pero recuerde, el prototipo de DogObject
es un objeto (par de clave y valor), por lo que también tiene una propiedad __proto__
que se refiere al protoype global Object
.
Esta técnica se conoce como ENCADENAMIENTO DE PROTOTIPOS.
Tenga en cuenta que: el enfoque de palabra clave new
hace lo mismo que Object.create()
, pero solo lo hace más fácil, ya que hace algunas cosas automáticamente para usted.
Y así…
Cada objeto en Javascript tiene acceso al prototipo de Object
por defecto. Si está configurado para usar otro prototipo, diga prototype2
, entonces prototype2
también tendría acceso al prototipo del objeto de forma predeterminada, y así sucesivamente.
Combinación de objeto y función
Probablemente esté confundido por el hecho de que DogObject
es una función (function DogObject(){}
) y tiene propiedades a las que se accede con una notación de puntos. Esto se conoce como una combinación de objetos de función.
Cuando se declaran funciones, por defecto se les dan muchas propiedades adjuntas a ellas. Recuerde que las funciones también son objetos en tipos de datos JavaScript.
Ahora, Class
JavaScript introdujo la palabra clave class
en ECMAScript 2015. Hace que JavaScript parezca un lenguaje de programación orientada a objetos. Pero es solo azúcar sintática sobre la técnica de creación de prototipos existente. Continúa su creación de prototipos en el fondo, pero hace que el cuerpo exterior se vea como OOP. Ahora veremos cómo es posible.
El siguiente ejemplo es un uso general de un class
en JavaScript:
class Animals { constructor(name, specie) { this.name = name; this.specie = specie; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; }}let bingo = new Animals("Bingo", "Hairy");console.log(bingo);
Este es el resultado en la consola:
El __proto__
referencias Animals
prototipo (que a su vez hace referencia el Object
prototipo).
De esto, podemos ver que el constructor define las características principales, mientras que todo lo que está fuera del constructor (sing()
y dance()
) son las características adicionales (prototipos).
En segundo plano, utilizando el enfoque de palabras clave new
, lo anterior se traduce en:
function Animals(name, specie) { this.name = name; this.specie = specie;}Animals.prototype.sing = function(){ return `${this.name} can sing`;}Animals.prototype.dance = function() { return `${this.name} can dance`;}let Bingo = new Animals("Bingo", "Hairy");
Subclase
Esta es una característica en OOP donde una clase hereda características de una clase padre, pero posee características adicionales que la madre no.
La idea aquí es, por ejemplo,, digamos que quieres crear una clase de gatos. En lugar de crear la clase desde cero, indicando de nuevo el nombre, la edad y la propiedad de la especie, heredaría esas propiedades de la clase animales padre.
Esta clase de gatos puede tener propiedades adicionales como el color de los bigotes.
Veamos cómo se hacen las subclases con class
.
Aquí, necesitamos un padre del que hereda la subclase. Examinar el código siguiente:
class Animals { constructor(name, age) { this.name = name; this.age = age; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; }} class Cats extends Animals { constructor(name, age, whiskerColor) { super(name, age); this.whiskerColor = whiskerColor; } whiskers() { return `I have ${this.whiskerColor} whiskers`; }}let clara = new Cats("Clara", 33, "indigo");
Con lo anterior, podemos obtener los siguientes resultados:
console.log(clara.sing());console.log(clara.whiskers());// Expected Output// "Clara can sing"// "I have indigo whiskers"
Cuando usted se registra el contenido de clara en la consola, tenemos:
Notará que clara
tiene una propiedad __proto__
que hace referencia al constructor Cats
y obtiene acceso a la propiedad whiskers()
método. Este __proto__
propiedad también dispone de un __proto__
propiedad que hace referencia el constructor Animals
por lo tanto, obtener acceso a sing()
y dance()
name
y age
son propiedades que existen en cada objeto creado a partir de esto.
con el Object.create
método de enfoque, lo anterior se traduce en:
function Animals(name, age) { let newAnimal = Object.create(animalConstructor); newAnimal.name = name; newAnimal.age = age; return newAnimal;}let animalConstructor = { sing: function() { return `${this.name} can sing`; }, dance: function() { return `${this.name} can dance`; }}function Cats(name, age, whiskerColor) { let newCat = Animals(name, age); Object.setPrototypeOf(newCat, catConstructor); newCat.whiskerColor = whiskerColor; return newCat;}let catConstructor = { whiskers() { return `I have ${this.whiskerColor} whiskers`; }}Object.setPrototypeOf(catConstructor, animalConstructor);const clara = Cats("Clara", 33, "purple");clara.sing();clara.whiskers();// Expected Output// "Clara can sing"// "I have purple whiskers"
Object.setPrototypeOf
es un método que toma dos argumentos: el objeto (primer argumento) y el prototipo (segundo argumento).
De lo anterior, la función Animals
devuelve un objeto con el animalConstructor
como prototipo. La función Cats
devuelve un objeto con catConstructor
como prototipo. catConstructor
por otro lado, se da un prototipo de animalConstructor
.
Por lo tanto, los animales comunes solo tienen acceso al animalConstructor
, pero los gatos tienen acceso al catConstructor
y al animalConstructor
.
Terminando
JavaScript aprovecha su naturaleza de prototipo para dar la bienvenida a los desarrolladores de OOP a su ecosistema. También proporciona formas fáciles de crear prototipos y organizar los datos relacionados.
Los lenguajes de programación orientada a objetos verdaderos no realizan prototipos en segundo plano, solo tome nota de ello.
Muchas gracias al curso de Will Sentance sobre Maestros de Frontend-JavaScript: Las Partes Duras de JavaScript Orientado a Objetos. Aprendí todo lo que ves en este artículo (más un poco de investigación adicional) de su curso. Deberías echarle un vistazo.
Puedes contactarme en Twitter en iamdillion para cualquier pregunta o contribución.
Gracias por leer : )