Los tipos de programación orientada a objetos (en JavaScript)

- ¿Qué es la programación orientada a objetos?
- Los cuatro sabores de la programación orientada a objetos.
- Declarar propiedades y métodos
- Dónde declarar propiedades y métodos
- Veredicto preliminar
- Clases versus funciones de fábrica: herencia
- Clases versus funciones de fábrica: encapsulación
En mi investigación, descubrí que existen cuatro enfoques para la programación orientada a objetos en JavaScript:
- Usando funciones de constructor
- Usando clases
- Uso de objetos vinculados a otros objetos (OLOO)
- Uso de funciones de fábrica
¿Qué métodos debo utilizar? ¿Cuál es “la mejor” manera? Aquí presentaré mis hallazgos junto con información que puede ayudarle a decidir cuál es el adecuado para usted.
Para tomar esa decisión, no solo veremos los diferentes sabores sino que compararemos aspectos conceptuales entre ellos:
- Clases versus funciones de fábrica: herencia
- Clases versus funciones de fábrica: encapsulación
- Clases versus funciones de fábrica –
this
- Clases frente a funciones de fábrica: oyentes de eventos
Comenzamos con una base de programación orientada a objetos en JavaScript.
¿Qué es la programación orientada a objetos?
La Programación Orientada a Objetos es una forma de escribir código que permite crear diferentes objetos a partir de un objeto común. El objeto común suele denominarse plano, mientras que los objetos creados se denominan instancias.
Cada instancia tiene propiedades que no se comparten con otras instancias. Por ejemplo, si tiene un plano humano, puede crear instancias humanas con nombres diferentes.
El segundo aspecto de la programación orientada a objetos tiene que ver con la estructuración del código cuando tienes múltiples niveles de planos. Esto comúnmente se llama herencia o subclasificación.
El tercer aspecto de la programación orientada a objetos tiene que ver con la encapsulación, donde se ocultan ciertas piezas de información dentro del objeto para que no sean accesibles.
Si necesita más que esta breve introducción, aquí tiene un artículo que presenta este aspecto de la programación orientada a objetos si necesita ayuda.
Comenzamos con lo básico: una introducción a los cuatro tipos de programación orientada a objetos.
Los cuatro sabores de la programación orientada a objetos.
Hay cuatro formas de escribir programación orientada a objetos en JavaScript. Ellos hijo:
- Usando funciones de constructor
- Usando clases
- Uso de objetos vinculados a otros objetos (OLOO)
- Uso de funciones de fábrica
Usando funciones de constructor
Los constructores son funciones que contienen una this
palabra clave.
function Human (firstName, lastName) { this.firstName = firstName this.lastName = lastName}
this
le permite almacenar (y acceder) a valores únicos creados para cada instancia. Puede crear una instancia con la new
palabra clave.
const chris = new Human('Chris', 'Coyier')console.log(chris.firstName) // Chrisconsole.log(chris.lastName) // Coyierconst zell = new Human('Zell', 'Liew')console.log(zell.firstName) // Zellconsole.log(zell.lastName) // Liew
Sintaxis de clase
Se dice que las clases son el “azúcar sintáctico” de las funciones del constructor. Como en, las clases son una forma más sencilla de escribir funciones de constructor.
Existe una seria controversia sobre si las clases son malas (como ésta y ésta). No vamos a profundizar aquí en esos argumentos. En lugar de eso, simplemente veremos cómo escribir código con clases y decidiremos si las clases son mejores que los constructores según el código que escribimos.
Las clases se pueden escribir con la siguiente sintaxis:
class Human { constructor(firstName, lastName) { this.firstName = firstName this.lastName = lastName }}
¿Observa que la constructor
función contiene el mismo código que la sintaxis del constructor anterior? Necesitamos hacer esto ya que queremos inicializar valores en this
. (Podemos omitirlo constructor
si no necesitamos inicializar valores. Más sobre esto más adelante en Herencia).
A primera vista, las clases parecen ser inferiores a los constructores: ¡hay más código para escribir! Mantenga sus caballos y no llegue a ninguna conclusión en este punto. Tenemos mucho más que cubrir. Las clases empiezan a brillar más tarde.
Como antes, puedes crear una instancia con la new
palabra clave.
const chris = new Human('Chris', 'Coyier')console.log(chris.firstName) // Chrisconsole.log(chris.lastName) // Coyier
Objetos vinculados a otros objetos (OLOO)
OLOO fue acuñado y popularizado por Kyle Simpson. En OLOO, define el plano como un objeto normal. Luego usa un método (a menudo llamado init
, pero que no es necesario en el sentido constructor
de una Clase) para inicializar la instancia.
const Human = { init (firstName, lastName ) { this.firstName = firstName this.lastName = lastName }}
Se utiliza Object.create
para crear una instancia. Después de crear la instancia, debe ejecutar su init
función.
const chris = Object.create(Human)chris.init('Chris', 'Coyier')console.log(chris.firstName) // Chrisconsole.log(chris.lastName) // Coyier
Puedes encadenar init
después Object.create
si regresaste this
adentro init
.
const Human = { init () { // ... return this }}const chris = Object.create(Human).init('Chris', 'Coyier')console.log(chris.firstName) // Chrisconsole.log(chris.lastName) // Coyier
Funciones de fábrica
Las funciones de fábrica son funciones que devuelven un objeto. Puedes devolver cualquier objeto. Incluso puedes devolver una instancia de Class o una instancia de OLOO, y seguirá siendo una función de Factory válida.
Esta es la forma más sencilla de crear funciones de fábrica:
function Human (firstName, lastName) { return { firstName, lastName }}
No es necesario new
crear instancias con funciones de fábrica. Simplemente llama a la función.
const chris = Human('Chris', 'Coyier')console.log(chris.firstName) // Chrisconsole.log(chris.lastName) // Coyier
Ahora que hemos visto estas cuatro posibilidades de configuración de programación orientada a objetos, veamos cómo se declaran propiedades y métodos en cada una de ellas para que podamos comprender un poco mejor cómo trabajar con ellas antes de pasar a las comparaciones más importantes que estamos tratando de hacer.
Declarar propiedades y métodos
Los métodos son funciones declaradas como propiedad de un objeto.
const someObject = { someMethod () { /* ... */ }}
En programación orientada a objetos, hay dos formas de declarar propiedades y métodos:
- Directamente en la instancia
- en el prototipo
Aprendamos a hacer ambas cosas.
Declarar propiedades y métodos con constructores
Si desea declarar una propiedad directamente en una instancia, puede escribir la propiedad dentro de la función constructora. Asegúrese de establecerlo como propiedad para this
.
function Human (firstName, lastName) { // Declares properties this.firstName = firstName this.lastname = lastName // Declares methods this.sayHello = function () { console.log(`Hello, I'm ${firstName}`) }}const chris = new Human('Chris', 'Coyier')console.log(chris)
Los métodos se declaran combinados en el Prototipo porque el Prototipo permite que las instancias utilicen el mismo método. Es una “huella de código” más pequeña.
Para declarar propiedades en el Prototipo, debe utilizar la prototype
propiedad.
function Human (firstName, lastName) { this.firstName = firstName this.lastname = lastName}// Declaring method on a prototypeHuman.prototype.sayHello = function () { console.log(`Hello, I'm ${this.firstName}`)}
Puede resultar complicado si desea declarar varios métodos en un prototipo.
// Declaring methods on a prototypeHuman.prototype.method1 = function () { /*...*/ }Human.prototype.method2 = function () { /*...*/ }Human.prototype.method3 = function () { /*...*/ }
Puede facilitar las cosas utilizando funciones de combinación como Object.assign
.
Object.assign(Human.prototype, { method1 () { /*...*/ }, method2 () { /*...*/ }, method3 () { /*...*/ }})
Object.assign
no admite la fusión de funciones Getter y Setter. Necesitas otra herramienta. Este es el por qué. Y aquí hay una herramienta que creé para fusionar objetos con Getters y Setters.
Declarar propiedades y métodos con clases
Puede declarar propiedades para cada instancia dentro de la constructor
función.
class Human { constructor (firstName, lastName) { this.firstName = firstName this.lastname = lastName this.sayHello = function () { console.log(`Hello, I'm ${firstName}`) } }}
Es más fácil declarar métodos en el prototipo. Escribe el método después constructor
como una función normal.
class Human (firstName, lastName) { constructor (firstName, lastName) { /* ... */ } sayHello () { console.log(`Hello, I'm ${this.firstName}`) }}
Es más fácil declarar múltiples métodos en clases en comparación con constructores. No necesitas la Object.assign
sintaxis. Simplemente escribe más funciones.
Nota: no hay ,
declaraciones entre métodos en una clase.
class Human (firstName, lastName) { constructor (firstName, lastName) { /* ... */ } method1 () { /*...*/ } method2 () { /*...*/ } method3 () { /*...*/ }}
Declarando propiedades y métodos con OLOO
Utilice el mismo proceso para declarar propiedades y métodos en una instancia. Los asignas como propiedad de this
.
const Human = { init (firstName, lastName) { this.firstName = firstName this.lastName = lastName this.sayHello = function () { console.log(`Hello, I'm ${firstName}`) } return this }}const chris = Object.create(Human).init('Chris', 'Coyier')console.log(chris)
Para declarar métodos en el prototipo, escribe el método como un objeto normal.
const Human = { init () { /*...*/ }, sayHello () { console.log(`Hello, I'm ${this.firstName}`) }}
Declarar propiedades y métodos con funciones de fábrica
Puede declarar propiedades y métodos directamente incluyéndolos en el objeto devuelto.
function Human (firstName, lastName) { return { firstName, lastName, sayHello () { console.log(`Hello, I'm ${firstName}`) } }}
No puede declarar métodos en el Prototipo cuando usa funciones de fábrica. Si realmente desea métodos en el prototipo, debe devolver una instancia de Constructor, Clase o OLOO. (No hagas esto ya que no tiene ningún sentido).
// Do not do thisfunction createHuman (...args) { return new Human(...args)}
Dónde declarar propiedades y métodos
¿Debería declarar propiedades y métodos directamente en la instancia? ¿O deberías usar prototype
tanto como puedas?
Mucha gente se enorgullece de que JavaScript sea un "lenguaje prototipo" (lo que significa que utiliza prototipos). A partir de esta afirmación, se puede suponer que utilizar “prototipos” es mejor.
La verdadera respuesta es: no importa.
Si declara propiedades y métodos en instancias, cada instancia ocupará un poco más de memoria. Si declara métodos en Prototipos, la memoria utilizada por cada instancia disminuirá, pero no mucho. Esta diferencia es insignificante con la potencia de procesamiento de las computadoras que es hoy. En lugar de eso, desea ver lo fácil que es escribir código y, en primer lugar, si es posible utilizar prototipos.
Por ejemplo, si usa Clases u OLOO, será mejor que use Prototipos ya que el código es más fácil de escribir. Si usa funciones de fábrica, no puede usar prototipos. Solo puede crear propiedades y métodos directamente en la instancia.
Escribí un artículo aparte sobre cómo entender los prototipos de JavaScript si estás interesado en saber más.
Veredicto preliminar
Podemos tomar algunas notas del código que escribimos anteriormente. ¡Estas opiniones son mías!
- Las clases son mejores que los constructores porque es más fácil escribir múltiples métodos en clases.
- OLOO es raro por el
Object.create
papel. Probé OLOO por un tiempo, pero siempre me olvido de escribirObject.create
. Ya es bastante extraño para mí no usarlo. - Las clases y funciones de Factry son las más fáciles de usar. El problema es que las funciones de fábrica no admiten prototipos. Pero como dije, esto realmente no importa en la producción.
Nos quedamos con dos. ¿Deberíamos entonces elegir Clases o funciones de Fábrica? ¡Vamos a compararlos!
Clases versus funciones de fábrica: herencia
Para continuar la discusión sobre clases y funciones de fábrica, necesitamos comprender tres conceptos más que están estrechamente relacionados con la programación orientada a objetos.
- Herencia
- Encapsulación
this
Empecemos por la herencia.
¿Qué es la herencia?
Herencia es una palabra cargada. En mi opinión, muchas personas en la industria usan la herencia de manera incorrecta. La palabra “herencia” se usa cuando recibes cosas de algún lugar. Por ejemplo:
- Si recibes una herencia de tus padres, significa que obtienes dinero y bienes de ellos.
- Si heredas genes de tus padres, significa que obtienes tus genes de ellos.
- Si heredas un proceso de tu maestro, significa que obtienes ese proceso de él.
Bastante sencillo.
En JavaScript, Herencia puede significar lo mismo: dónde se obtienen propiedades y métodos del modelo principal.
Esto significa que todas las instancias heredan de sus planos . Heredan propiedades y métodos de dos maneras:
- creando una propiedad o método directamente al crear la instancia
- a través de la cadena Prototype
Discutimos cómo realizar ambos métodos en el artículo anterior, así que consúltelo si necesita ayuda para ver estos procesos en el código.
Hay un segundo significado para Herencia en JavaScript: donde se crea un modelo derivado del modelo principal. Este proceso se llama más exactamente Subclasificación, pero a veces la gente también lo llama Herencia.
Comprender las subclases
La subclasificación consiste en crear un modelo derivado a partir de un modelo común. Puede utilizar cualquier tipo de programación orientada a objetos para crear la subclase.
Primero hablaremos de esto con la sintaxis de Clase porque es más fácil de entender.
Subclases con clase
Cuando creas una subclase, utilizas la extends
palabra clave.
class Child extends Parent { // ... Stuff goes here}
Por ejemplo, digamos que queremos crear una Developer
clase a partir de una Human
clase.
// Human Classclass Human { constructor (firstName, lastName) { this.firstName = firstName this.lastName = lastName } sayHello () { console.log(`Hello, I'm ${this.firstName}`) }}
La Developer
clase se extenderá Human
así:
class Developer extends Human { constructor(firstName, lastName) { super(firstName, lastName) } // Add other methods}
Nota: super
llama a la Human
clase (también llamada “principal”). Inicia el constructor
from Human
. Si no necesita un código de inicio adicional, puede omitirlo constructor
por completo.
class Developer extends Human { // Add other methods}
Digamos un Developer
código de lata. Podemos agregar el code
método directamente a Developer
.
class Developer extends Human { code (thing) { console.log(`${this.firstName} coded ${thing}`) }}
A continuación se muestra un ejemplo de una instancia de Developer
:
const chris = new Developer('Chris', 'Coyier')console.log(chris)
Subclases con funciones de fábrica
Hay cuatro pasos para crear subclases con funciones de fábrica:
- Crear una nueva función de fábrica
- Crear una instancia del plano principal
- Crear una nueva copia de esta instancia
- Agregue propiedades y métodos a esta nueva copia.
El proceso se ve así:
function Subclass (...args) { const instance = ParentClass(...args) return Object.assign({}, instance, { // Properties and methods go here })}
Usaremos el mismo ejemplo (creación de una Developer
subclase) para ilustrar este proceso. Aquí está la Human
función de fábrica:
function Human (firstName, lastName) { return { firstName, lastName, sayHello () { console.log(`Hello, I'm ${firstName}`) } }}
Podemos crear Developer
así:
function Developer (firstName, lastName) { const human = Human(firstName, lastName) return Object.assign({}, human, { // Properties and methods go here })}
Luego agregamos el code
método así:
function Developer (firstName, lastName) { const human = Human(firstName, lastName) return Object.assign({}, human, { code (thing) { console.log(`${this.firstName} coded ${thing}`) } })}
A continuación se muestra un ejemplo de una Developer
instancia:
const chris = Developer('Chris', 'Coyier')console.log(chris)
Nota: No puede usarlo Object.assign
si usa Getters y Setters. Necesitará otra herramienta, como mix
. Te explico por qué en este artículo.
Sobrescribiendo el método de los padres
A veces es necesario sobrescribir el método principal dentro de la subclase. Puedes hacer esto mediante:
- Creando un método con el mismo nombre
- Llamar al método de los padres (opcional)
- Cambiando lo que necesites en el método de la Subclase
El proceso se ve así con Clases:
class Developer extends Human { sayHello () { // Calls the parent method super.sayHello() // Additional stuff to run console.log(`I'm a developer.`) }}const chris = new Developer('Chris', 'Coyier')chris.sayHello()
El proceso se ve así con las funciones de fábrica:
function Developer (firstName, lastName) { const human = Human(firstName, lastName) return Object.assign({}, human, { sayHello () { // Calls the parent method human.sayHello() // Additional stuff to run console.log(`I'm a developer.`) } })}const chris = new Developer('Chris', 'Coyier')chris.sayHello()
Herencia versus composición
Ninguna conversación sobre Herencia concluye sin la mención de Composición. Expertos como Eric Elliot suelen sugerir que deberíamos favorecer la composición sobre la herencia.
“Favorecer la composición de objetos sobre la herencia de clases” la Banda de los Cuatro, “Patrones de diseño: elementos de software orientado a objetos reutilizables”
“En informática, un tipo de datos compuestos o tipo de datos compuestos es cualquier tipo de datos que se puede construir en un programa utilizando los tipos de datos primitivos del lenguaje de programación y otros tipos compuestos. […] El acto de construir un tipo compuesto se conoce como composición”. ~Wikipedia
Entonces, echemos un vistazo más profundo a la composición y comprendamos qué es.
Comprender la composición
La composición es el acto de combinar dos cosas en una. Se trata de fusionar cosas. La forma más común (y sencilla) de fusionar objetos es con Object.assign
.
const one = { one: 'one' }const two = { two: 'two' }const combined = Object.assign({}, one, two)
El uso de Composición se puede explicar mejor con un ejemplo. Digamos que ya tenemos dos subclases, a Designer
y Developer
. Los diseñadores pueden diseñar, mientras que los desarrolladores pueden codificar. Tanto los diseñadores como los desarrolladores heredan de la Human
clase.
Aquí está el código hasta el momento:
class Human { constructor(firstName, lastName) { this.firstName = firstName this.lastName = lastName } sayHello () { console.log(`Hello, I'm ${this.firstName}`) }}class Designer extends Human { design (thing) { console.log(`${this.firstName} designed ${thing}`) }}class Developer extends Designer { code (thing) { console.log(`${this.firstName} coded ${thing}`) }}
Ahora digamos que desea crear una tercera subclase. Esta subclase es una combinación de diseñador y desarrollador: pueden diseñar y codificar. Llamémoslo DesignerDeveloper
(o DeveloperDesigner
como quieras).
¿Cómo crearías la tercera subclase?
No podemos ampliar Designer
y Developer
clases al mismo tiempo. Esto es imposible porque no podemos decidir qué propiedades vienen primero. A esto se le suele llamar el problema del diamante.
El problema del diamante se puede resolver fácilmente si hacemos algo como Object.assign
: priorizar un objeto sobre el otro. Si utilizamos este Object.assign
enfoque, es posible que podamos ampliar clases como esta. Pero esto no es compatible con JavaScript.
// Doesn't workclass DesignerDeveloper extends Developer, Designer { // ...}
Entonces debemos confiar en la Composición.
La composición dice: en lugar de intentar crear DesignerDeveloper
mediante subclases, creemos un nuevo objeto que almacene características comunes. Luego podremos incluir estas características cuando sea necesario.
En la práctica, puede verse así:
const skills = { code (thing) { /* ... */ }, design (thing) { /* ... */ }, sayHello () { /* ... */ }}
Luego podemos omitirlo Human
por completo y crear tres clases diferentes según sus habilidades.
Aquí está el código para DesignerDeveloper
:
class DesignerDeveloper { constructor (firstName, lastName) { this.firstName = firstName this.lastName = lastName Object.assign(this, { code: skills.code, design: skills.design, sayHello: skills.sayHello }) }}const chris = new DesignerDeveloper('Chris', 'Coyier')console.log(chris)
Puedes hacer lo mismo con Developer
y Designer
.
class Designer { constructor (firstName, lastName) { this.firstName = firstName this.lastName = lastName Object.assign(this, { design: skills.design, sayHello: skills.sayHello }) }}class Developer { constructor (firstName, lastName) { this.firstName = firstName this.lastName = lastName Object.assign(this, { code: skills.code, sayHello: skills.sayHello }) }}
¿Notaste que estamos creando métodos directamente en la instancia? Ésta es sólo una opción. Todavía podemos incluir métodos en el prototipo, pero creo que el código parece complicado. (Es como si estuviéramos escribiendo funciones de Constructor de nuevo).
class DesignerDeveloper { constructor (firstName, lastName) { this.firstName = firstName this.lastName = lastName }}Object.assign(DesignerDeveloper.prototype, { code: skills.code, design: skills.design, sayHello: skills.sayHello})
Siéntete libre de utilizar cualquier estructura de código que te atraiga. Los resultados son más o menos los mismos de todos modos.
Composición con funciones de fábrica
La composición con funciones de fábrica consiste esencialmente en agregar los métodos compartidos al objeto devuelto.
function DesignerDeveloper (firstName, lastName) { return { firstName, lastName, code: skills.code, design: skills.design, sayHello: skills.sayHello }}
Herencia y Composición al mismo tiempo
Nadie dice que no podamos usar Herencia y Composición al mismo tiempo. ¡Podemos!
Usando el ejemplo que hemos resuelto hasta ahora, Designer
, Developer
y DesignerDeveloper
Humans
todavía somos humanos. Pueden ampliar el Human
objeto.
A continuación se muestra un ejemplo en el que utilizamos tanto la herencia como la composición con la sintaxis de la clase.
class Human { constructor (firstName, lastName) { this.firstName = firstName this.lastName = lastName } sayHello () { console.log(`Hello, I'm ${this.firstName}`) }}class DesignerDeveloper extends Human {}Object.assign(DesignerDeveloper.prototype, { code: skills.code, design: skills.design})
Y ocurre lo mismo con las funciones de fábrica:
function Human (firstName, lastName) { return { firstName, lastName, sayHello () { console.log(`Hello, I'm ${this.firstName}`) } }}function DesignerDeveloper (firstName, lastName) { const human = Human(firstName, lastName) return Object.assign({}, human, { code: skills.code, design: skills.design }}
Subclases en el mundo real
Un último punto sobre subclases versus composición. Aunque los expertos han señalado que la composición es más flexible (y por tanto más útil), la subclasificación sigue teniendo sus ventajas. Muchas cosas que usamos hoy se crean con la estrategia de subclases.
Por ejemplo: el click
evento que conocemos y amamos es un MouseEvent
. MouseEvent
es una subclase de a UIEvent
, que a su vez es una subclase de Event
.
Otro ejemplo: los elementos HTML son subclases de nodos. Es por eso que pueden usar todas las propiedades y métodos de Nodes.
Veredicto preliminar
Las clases y las funciones de fábrica pueden usar herencia y composición. Sin embargo, la composición parece ser más limpia en las funciones de fábrica, pero eso no es una gran victoria sobre las clases.
A continuación examinaremos las clases y funciones de fábrica con más detalle.
Clases versus funciones de fábrica: encapsulación
Hasta ahora hemos analizado los cuatro tipos diferentes de programación orientada a objetos. Dos de ellos (clases y funciones de fábrica) son más fáciles de usar en comparación con el resto.
Pero las preguntas persisten: ¿cuál debería utilizar? ¿Y por qué?
Para continuar la discusión sobre Clases y funciones de Fábrica, necesitamos comprender tres conceptos que están estrechamente relacionados con la Programación Orientada a Objetos:
- Herencia
- Encapsulación
this
Acabamos de hablar de herencia. Ahora hablemos de encapsulación.
Encapsulación
Encapsulación es una palabra grande , pero tiene un significado simple. La encapsulación es el acto de encerrar una cosa dentro de otra para que lo que está dentro no se escape. Piense en almacenar agua dentro de una botella. La botella evita que el agua se escape.
En JavaScript, estamos interesados en encerrar variables (que pueden incluir funciones) para que estas variables no se filtren al ámbito externo. Esto significa que es necesario comprender el alcance para comprender la encapsulación. Revisaremos una explicación, pero también puede utilizar este artículo para reforzar sus conocimientos sobre los alcances.
Encapsulación sencilla
La forma más simple de encapsulación es un alcance de bloque.
{ // Variables declared here won't leak out}
Cuando estás en el bloque, puedes acceder a variables que están declaradas fuera del bloque.
const food = 'Hamburger'{ console.log(food)}
Pero cuando estás fuera del bloque, no puedes acceder a las variables declaradas dentro del bloque.
{ const food = 'Hamburger'}console.log(food)
Nota: Las variables declaradas con var
no respetan el alcance del bloque. Por eso te recomiendo que uses let
o const
para declarar variables.
Encapsulando con funciones
Las funciones se comportan como ámbitos de bloque. Cuando declaras una variable dentro de una función, no pueden filtrarse fuera de esa función. Esto funciona para todas las variables, incluso aquellas declaradas con var
.
function sayFood () { const food = 'Hamburger'}sayFood()console.log(food)
Del mismo modo, cuando estás dentro de la función, puedes acceder a variables que están declaradas fuera de esa función.
const food = 'Hamburger'function sayFood () { console.log(food)}sayFood()
Las funciones pueden devolver un valor. Este valor devuelto se puede utilizar más adelante, fuera de la función.
function sayFood () { return 'Hamburger'}console.log(sayFood())
Cierres
Los cierres son una forma avanzada de encapsulación. Son simplemente funciones envueltas en funciones.
// Here's a closurefunction outsideFunction () { function insideFunction () { /* ...*/ }}
Las variables declaradas en outsideFunction
se pueden utilizar en insideFunction
.
function outsideFunction () { const food = 'Hambur
Deja un comentario