A medida que avanzamos hacia el final de esta sección,
tenemos que aprender acerca de la gran diferencia
entre la forma en que los tipos primitivos y los objetos
se almacenan y la memoria.
Y esto es en realidad un aspecto muy práctico.
y uno que causa mucha confusión en los principiantes.
Así que comencemos escribiendo algo de código esta vez
para entender cuál es la confusión en realidad,
para que luego pueda mostrarte
cómo funciona todo detrás de escena.
Así que ahora mismo no voy a explicar
cómo funciona el código que veremos ahora,
pero solo les mostraré cuál es la fuente de confusión.
Pero por ahora empecemos con
un ejemplo simple con primitivas.
Y recuerda que las primitivas son como números,
cadenas, booleanos, etcétera.
Así que simplemente establecer la edad en 30,
y luego estoy creando una variable de vejez.
Y éste lo pondré en la edad
porque ahora es mi cumpleaños básicamente.
Y así mi edad cambia a 31,
pero aún quería preservar mi vejez aquí
en esta variable.
¿Bueno?
Entonces registremos los resultados en la consola ahora.
Y deberían ser más o menos lo que esperamos en este momento.
Entonces ves que mi edad actual es 31 porque, bueno,
Cambié el original de 30 a 31.
Pero la vejez sigue siendo 30 aquí.
Y eso es porque lo configuré aquí en este punto del código.
a la edad, que todavía era 30 en este punto.
Y entonces cambiando la edad aquí de 30 a 31
por supuesto, no volvió a afectar la variable de la vejez.
Nuevamente porque en este punto aquí la edad todavía era 30.
Muy bien, así que aquí, espero que no haya mucha confusión,
todo funciona como se esperaba.
Pero ahora vamos a crear otro escenario que tenga un objeto.
Así que simplemente voy a crear un objeto para mí,
con el nombre de Jonas y 30 años.
Y ahora copiemos este objeto.
porque digamos que tengo un amigo
que también se llama Jonas.
Y así, en lugar de crear un objeto completamente nuevo desde cero,
Simplemente copiaría el objeto me.
Entonces const Amigo es igual a Mí.
¿Bueno?
Y ahora tanto el nombre como la edad son los mismos,
pero digamos que tenemos diferentes edades.
Y entonces cambiemos la edad de mi amigo
y eso es bastante sencillo, ¿verdad?
Así que digamos que tiene 27 años.
Pero, por supuesto, no me cambiamos la edad, ¿verdad?
Así que ahora echemos un vistazo a ambos en la consola.
Así que primero mi amigo,
así que ese es el objeto Amigo y luego también Yo,
o podríamos decir Jonas, en realidad no importa.
Pero lo que importa es que veremos el objeto Me
y ¿qué creemos que pasará ahora?
Así que déjame mostrártelo.
Y ahora entendemos que tanto yo como mi amigo
tener la edad de 27.
Y eso se ve un poco extraño porque todo lo que hicimos
era cambiar la edad del amigo, ¿no?
Aquí en ninguna parte, me tengo. La edad es igual a 27,
pero aún para mí mismo, así que aquí en el objeto Me,
la edad tambien es 27
Y eso es lo que quiero decir con fuente de confusión.
Y así en este video,
Veamos ahora por qué funciona de esta manera.
Ahora, antes de que podamos entender el código que acabamos de escribir,
Necesitamos revisar algunos conceptos básicos aquí.
En primer lugar, debemos recordar acerca de
Tipos de datos primitivos de JavaScript,
que son número, cadena, booleano, indefinido, nulo, símbolo,
y BigInt.
Entonces todo lo demás son básicamente objetos.
Así que los objetos creados con el objeto literal, matrices
e incluso las funciones son todos objetos.
Ahora, cuando hablamos de memoria y administración de memoria,
es habitual llamar primitivos, tipos primitivos
y tipos de referencia de objetos debido a la forma diferente
en el que se almacenan en la memoria.
A continuación, debemos recordar sobre el motor de JavaScript.
Entonces, el motor tiene dos componentes, la pila de llamadas,
donde se ejecutan las funciones y en el montón donde se ejecutan los objetos
se almacenan en la memoria.
Y así es, todos los objetos,
o en otras palabras, tipos de referencia
se almacenará directamente en el montón de memoria.
Y mencioné que cuando hablamos por primera vez sobre el motor,
pero ahora finalmente aprenderá cómo funciona eso realmente.
Por otro lado, los primitivos o tipos primitivos
se almacenan en la pila de llamadas.
Y con eso quiero decir que los tipos primitivos
se almacenan en los contextos de ejecución
en que se declaran.
Pero en aras de la simplicidad,
ignoremos ese detalle ahora.
Y simplemente decir que los tipos primitivos
se almacenan en una pila de llamadas
porque ahí es donde se ejecuta el contexto de ejecución.
Muy bien, pero ahora, ¿cómo funciona todo eso realmente?
¿Y por qué nuestro ejemplo de código anterior se comportó
de esa manera rara?
Bueno, averigüémoslo.
Así que aquí tenemos los dos ejemplos de código de antes,
así como el motor con la pila de llamadas y el montón.
Y comencemos mirando el ejemplo de valores primitivos.
Entonces, cuando declaramos una variable como la edad es igual a 30,
lo que realmente sucede dentro del motor de JavaScript
y la memoria de la computadora?
Bueno, primero JavaScript creará
un llamado identificador único con el nombre de la variable.
Luego se asignará una parte de la memoria.
con una determinada dirección, por lo que 0001 en este ejemplo,
y finalmente el valor se almacenaría en la memoria
en la dirección especificada.
Así que en este caso, el valor 30
se especificará en la dirección de memoria 0001.
Y recuerda que todo esto sucede en una pila de llamadas
donde se almacenan los valores primitivos.
Ahora, lo que es extremadamente importante entender aquí
es que el identificador en realidad apunta a la dirección
y no al valor mismo.
Entonces diríamos que la variable edad es igual a 30,
pero de hecho, la edad es igual a la dirección de memoria 0001,
que tiene el valor de 30, ¿de acuerdo?
Y esta sutil distinción
es muy importante tener en cuenta.
Ahora, en la siguiente línea, declaramos la vejez
ser igual a la edad.
Entonces, sabiendo que una variable en realidad tiene una dirección de memoria,
¿Cómo debe ser la vejez?
Bueno, simplemente apuntará a la misma dirección de memoria.
como la variable edad.
Y por lo que se verá como la vejez, es simplemente 30 también.
Genial, pero ahora en la siguiente línea, establecemos ocho a 31.
Entonces, ¿qué pasará entonces?
El valor en la dirección 0001
ciertamente no se convertirá en 31
porque eso también cambiaría la vejez,
ya que ambos apuntan a la misma dirección.
Así que eso no tendría ningún sentido en absoluto.
Además, el valor en una determinada dirección de memoria es inmutable,
o en otras palabras, no se puede cambiar.
Entonces, en cambio, ¿qué va a pasar aquí?
es que se asigna una nueva pieza de memoria.
Entonces se crea y el identificador de edad ahora simplemente apunta
a la nueva dirección, que contiene el nuevo valor de 31,
¿está bien?
Y por eso cuando cerramos los dos
o variables a la consola al final,
ambos devuelven exactamente los valores que esperamos.
Ahora con los valores de referencia, las cosas funcionan un poco diferente,
que es la razón por la que este ejemplo nos dio
ese inesperado y extraño comportamiento anterior en la práctica.
Entonces, ¿cuál es el origen de este extraño resultado inesperado?
Bueno, cuando se crea un nuevo objeto como este objeto Me,
se almacena en el montón.
Y como antes hay una dirección de memoria
y luego el valor en sí.
Ahora bien, en el caso de los valores de referencia
como este objeto Me el identificador Me
en realidad no apunta directamente
a esta dirección de memoria recién creada en el montón.
Entonces, en este ejemplo, D30F,
en cambio, apuntará a una nueva pieza de memoria
que se crea en la pila.
Y esta nueva pieza de memoria apuntará al objeto.
eso está en el montón usando la dirección de memoria como su valor.
En otras palabras, la pieza de memoria en la pila de llamadas
tiene una referencia a la pieza de memoria en el montón,
que sostiene o Me objeto, ¿de acuerdo?
Y esa es la razón por la que llamamos tipos de referencia a los objetos.
en este contexto.
De nuevo, cuando declaramos una variable como objeto,
se crea un identificador,
que apunta a una parte de la memoria en la pila,
que a su vez apunta a un fragmento de memoria en el montón.
Y ahí es donde se almacena realmente el objeto.
Y funciona de esta manera porque los objetos pueden ser
demasiado grande para ser almacenado en la pila.
En su lugar, se almacenan en el montón,
que es como un grupo de memoria casi ilimitado.
Y la pila solo mantiene una referencia.
a donde el objeto está realmente almacenado en el montón
para que pueda encontrarlo cuando sea necesario.
Ahora, avanzando en el código,
creamos una nueva variable llamada Amigo
que igualamos al objeto Me.
Entonces, ¿qué pasará aquí?
Bueno, al igual que con los valores primitivos,
el identificador de amigo señalará
exactamente a la misma dirección de memoria que el identificador Me.
Y de nuevo, esa dirección contiene la referencia,
que luego apunta al objeto mismo.
Y así, el objeto Amigo ahora es esencialmente
exactamente lo mismo que el objeto Me.
¿Ves eso aquí en el diagrama?
Así que aquí viene la parte interesante.
porque ahora vamos a cambiar una propiedad
en el objeto Amigo estableciendo friend.age en 27.
Entonces lo que sucede entonces es que el objeto
se encuentra en el montón, y el 30 se cambia a 27.
Excelente.
Y por cierto, aunque definimos la variable Amigo
como una constante, en realidad todavía podemos manipular el objeto
sin problemas.
Y cuando pensamos en eso, tiene sentido
porque en realidad no estamos cambiando el valor en la memoria
para el identificador de Amigo, sigue siendo D30F.
Así que la referencia al objeto.
Todo lo que hicimos fue cambiar el valor en el montón,
y eso no es un problema.
Así que es un error pensar que todas las variables declaradas
con const son inmutables.
De hecho, eso solo es cierto para valores primitivos,
pero no para valores de referencia.
Así que tenlo en cuenta cada vez que trabajes con const.
De todos modos, cuando bloqueamos la variable Amigo en la consola,
obtenemos la edad de 27, tal como lo dijimos antes.
Pero luego, cuando bloqueamos el objeto Me,
tenemos ese comportamiento extraño
que antes no podíamos explicar y no entender.
Pero con todo lo que aprendimos en esta conferencia,
en realidad ahora tiene sentido
que en el objeto Me, la edad ahora también es 27,
aunque nunca me cambiamos la edad directamente.
Y la razón de esto, como podemos ver en esta diapositiva
es el hecho de que yo y un amigo
en realidad apuntan exactamente al mismo objeto en el montón de memoria.
Así que cada vez que cambiamos algo en este objeto,
siempre se reflejará en el Amigo y en Mí.
Así que en estos dos objetos.
Estos son básicamente dos identificadores diferentes
apuntando exactamente al mismo valor.
Y una vez más, ese valor es la dirección de memoria D30F
que apunta a la referencia en el montón de memoria.
Y una implicación importante de esto
es que cada vez que piensas que estás copiando un objeto,
en realidad solo estás creando una nueva variable
que apunta exactamente al mismo objeto.
Y esto tiene enormes implicaciones.
por la forma en que JavaScript funciona en la práctica.
Y eso lo veremos en el siguiente video.
y durante todo el curso.
Ahora, en realidad hay formas de evitar esto,
como también aprenderemos más adelante.
pero en general, así es como funcionan los valores de referencia
en JavaScript.
Así que asegúrese de entender realmente esto,
así como las implicaciones que tiene este comportamiento,
incluso si eso significa que tienes que volver a ver esta conferencia
o al menos la explicación de esta diapositiva, ¿de acuerdo?
Luego, una vez que realmente entiendas lo que sucedió aquí,
en este ejemplo, entendamos los valores primitivos
y valores de referencia aún mejores en la práctica
en la próxima conferencia.
Pero antes de hacer eso, permítanme tomarme un segundo rápidamente
y mencionar otros tres temas realmente importantes
sobre cómo funciona JavaScript entre bastidores
que no estará en la sección,
pero más cerca de donde realmente necesitamos aprender sobre ellos.
Por ejemplo, un concepto fundamental de JavaScript
es la herencia prototípica.
Pero solo hablaremos de eso.
en la sección de programación orientada a objetos de este curso.
Porque no tiene sentido aprender sobre esto ahora.
solo para luego olvidarlo todo
hasta que finalmente llegamos a ese tramo.
Lo mismo es cierto para una lectura detallada sobre el bucle de eventos.
Así que ya introduje el bucle de eventos en esta sección,
pero en la sección sobre JavaScript asíncrono,
nos sumergiremos muy profundamente en
cómo funciona exactamente el bucle de eventos
y por qué es una pieza tan fundamental
del motor JavaScript.
Finalmente, tendremos conferencias sobre
cómo el DOM realmente funciona detrás de escena también.
y eso va a ser
en la sección avanzada de DOM y eventos
para que luego puedas aplicar
lo que aprendiste allí de inmediato.
¿Bueno?
Y dicho esto, ahora sigamos.