forked from gaearon/overreacted.io
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Translation to Spanish of "What Is JavaScript Made Of?" (gaearon#556)
* Translation to Spanish of "What Is JavaScript Made Of?" * Apply suggestions from code review Co-Authored-By: Rainer Martínez Fraga <rmartinezfraga@yandex.com> * Update index.es.md Co-authored-by: Rainer Martínez Fraga <rmartinezfraga@yandex.com>
- Loading branch information
Showing
1 changed file
with
63 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
title: ¿De qué está hecho JavaScript? | ||
date: '2019-12-20' | ||
spoiler: Una mirada detallada a JavaScript. | ||
--- | ||
|
||
Durante mis primeros años programando en JavaScript, me sentía como si fuese un fraude. Aunque era capaz de crear páginas web usando frameworks, había algo que se me escapaba. No tenía una base sólida de JavaScript y por ese motivo, temía ir a entrevistas de trabajo. | ||
|
||
Con el paso de los años, desarrollé un mapa mental con los fundamentos básicos de JavaScript y esto me dio confianza. Y ahora, quiero compartir una versión **comprimida** de todo ello. Está estructurado como un glosario, con cada tema resumido en unas pocas frases. | ||
|
||
A medida que vayas leyendo, intenta puntuar tus conocimientos en relación a cómo de *seguro* te sientes acerca de cada tema. ¡No te juzgaré si no tienes conocimientos en todos ellos! Al final del post, hay algo que podría ayudarte si este es tu caso. | ||
|
||
--- | ||
|
||
* **Valor**: El concepto de valor es un poco abstracto. Es un "algo". Un valor en JavaScript es lo mismo que un número a las matemáticas, o un punto en geometría. Cuando un programa se está ejecutando, su mundo está lleno de valores. Números como `1`, `2` y `420` son valores, igual que lo son otras cosas, como esta frase: `"Las vacas hacen mu"`. Aunque no *todo* es un valor, un número es un valor, pero una estructura de control `if` no lo es. A continuación, veremos algunos tipos de valores. | ||
- **Tipos de valor**: Existen varios "tipos" diferentes de valores. Por ejemplo, *números* como `420`, *cadenas de caracteres* como `"Las vacas hacen mu"`, *objetos* y algunos otros tipos más. Se puede ver el tipo de un valor poniendo `typeof` antes del valor. Por ejemplo, `console.log(typeof 2)` devuelve `"number"`. | ||
- **Valores primitivos**: Algunos tipos de valores son "primitivos". Se incluyen en esta categoría números, cadenas de caracteres y algunos otros tipos más. Una cosa peculiar de los valores primitivos es que no se pueden crear más tipos ni cambiarlos de ninguna manera. Por ejemplo, cada vez que escribes `2`, obtienes el *mismo* valor `2`. No puedes "crear" otro `2` en el programa, o hacer que el *valor* `2` se "convierta" en `3`. Esto también es cierto para las cadenas de caracteres. | ||
- **`null` y `undefined`**: Estos dos, son tipos especiales de valores. Son especiales porque hay muchas cosas que no se pueden hacer con ellos -- aunque a menudo causan errores. Por lo general, `null` representa la ausencia intencional de un valor, y `undefined` representa la ausencia involuntaria de un valor. Sin embargo, cuándo usarlos queda a disposición del programador. Existen porque a veces es mejor que una operación falle que proceder con la ausencia de un valor. | ||
|
||
* **Igualdad**: al igual que "valor", igualdad es un concepto fundamental en JavaScript. Decimos que dos valores son iguales cuando son... en realidad, yo nunca diría esto. Si dos valores son iguales, significa que *son* el mismo valor. ¡No dos valores diferentes, sino uno! Por ejemplo, `"Las vacas hacen mu" === "Las vacas hacen mu"` y `2 === 2` porque `2` *es* `2`. Ten en cuenta que usamos *tres* signos de igual para representar este concepto de igualdad en JavaScript. | ||
- **Igualdad estricta**: Igual que el ejemplo anterior. | ||
- **Igualdad referencial**: Igual que el ejemplo anterior. | ||
- **Igualdad estándar**: ¡Este es diferente! La igualdad estándar es cuando usamos *dos* signos de igual (`==`). Las cosas pueden ser consideradas *más o menos iguales* incluso si se refieren a valores *diferentes* que se parecen (por ejemplo, `2` y `"2"`). Se agregó a JavaScript desde el principio por conveniencia y desde entonces ha causado una confusión infinita. Este concepto no es fundamental, pero es una fuente común de errores. Puedes aprender cómo funciona en un día lluvioso, pero muchas personas intentan evitarlo. | ||
|
||
* **Literal**: Un literal es cuando nos referimos a un valor que escribimos *literalmente* en nuestro código. Por ejemplo, `2` es un *literal de número*, y `"Banana"` es un *literal de cadena*. | ||
|
||
* **Variable**: una variable permite referirse a un valor utilizando un nombre. Por ejemplo, `let mensaje = "Las vacas hacen mu"`. Ahora podrías utilizar `mensaje` en lugar de repetir la misma frase cada vez que quieras usarla en el código. Más tarde, podrías cambiar `mensaje` para que apunte a otro valor, como `mensaje = "Soy una morsa" `. Ten en cuenta que esto no cambia *el valor en sí*, sino solo donde apunta el `mensaje`, como si estuvieran "conectados". Antes apuntaba a `"Las vacas hacen mu"`, y ahora apunta a `"Soy una morsa"`. | ||
- **Alcance**: apestaría si solo pudiera haber una variable 'mensaje' en todo el programa. En cambio, cuando definimos una variable, esta está disponible en una *parte* del programa. Esa parte se llama "alcance". Existen reglas sobre cómo funciona el alcance, pero generalmente puedes buscar las llaves `{` y `}` más cercanas alrededor de donde una variable ha sido definida. Ese "bloque" de código es su alcance. | ||
- **Asignación**: cuando escribimos `mensaje = "Soy una morsa"`, cambiamos la variable `mensaje` para que apunte al valor `"Soy una morsa" `. Esto se denomina asignación, escritura o configuración de la variable. | ||
- **`let` vs` const` vs `var`**: Por lo general, querrás usar `let`. Si deseas prohibir la asignación a una variable, puedes usar `const`. (A veces algunas bases de código o tus compañeros de trabajo pueden ser un poco puntillosos y obligan a usar 'const' cuando solo hay una asignación). Evita 'var' si puedes porque sus reglas de Scope son confusas. | ||
|
||
* **Object**: Un objeto es un tipo especial de valor en JavaScript. Lo bueno de los objetos es que pueden tener conexiones con otros valores. Por ejemplo, el objeto `{sabor: "vainilla"}` contiene la propiedad `sabor` que apunta al valor `"vainilla"`. Piensa en un objeto como en un valor que es "tuyo" y tiene "conexiones desde él". | ||
- **Propiedad**: Una propiedad es como una conexión desde un objeto apuntando a un valor. Puede que esto te recuerde a una variable: tiene un nombre (como `sabor`) y apunta a un valor (como `"vainilla"`). Pero al contrario que una variable, una propiedad "vive" *en* en el propio objeto en lugar de en algún lugar del código (alcance). Una propiedad se considera parte de un objeto -- pero el valor al que apunta no es parte de ese objeto. | ||
- **Objeto Literal**: Un Objeto Literal es una manera de crear un valor en un objeto *literalmente* escribiéndolo en el código, como `{}` o `{sabor: "vainilla"}`. Dentro de `{}`, podemos tener múltiples pares `propiedad: valor` separados por comas. Esto nos permite indicar hacia donde "conecta" la propiedad desde nuestro objeto. | ||
- **Identidad del Objecto**: ya mencionamos que `2` es *igual* que `2` (en otras palabras, `2 === 2`) porque cuando escribimos `2`, estamos "llamando" al mismo valor. ¡Pero cuando escribimos `{}`, siempre recibiremos un valor *diferente*! Entonces `{}` *no es igual* a otro `{}`. Intenta esto en la consola: `{} === {}` (el resultado es false). Cuando el ordenador se encuentra `2` en tu código, siempre nos devuelve el mismo valor `2`. Sin embargo, los objetos literales son diferentes: cuando el ordenador se encuentra `{}`, *crea un nuevo objeto, el cual es siempre un valor nuevo*. Entonces, ¿qué es la identidad del objeto? Es simplemente otro término para igualdad, o igualdad de valores. Cuando decimos “`a` y `b` tienen la misma identidad", queremos decir que “`a` y `b` apuntan al *mismo* valor" (`a === b`). Cuando decimos “`a` y `b` tienen diferentes identidades", queremos decir “`a` y `b` apuntan a valores *diferentes*" (`a !== b`). | ||
- **Notación por punto**: Cuando queremos leer o asignar una propiedad a un objeto, podemos usar la notación por punto (`.`). Por ejemplo, si la variable `helado` apunta a un objeto en el que la propiedad `sabor` apunta a `"chocolate"`, escribir `helado.sabor` te devolvera `"chocolate"`. | ||
- **Notación por corchetes**: A veces no sabemos el nombre de la propiedad que queremos acceder. Por ejemplo, puede que unas veces queramos leer `helado.sabor` y otras `helado.gusto`. La notación por corchetes (`[]`) nos permite leer una propiedad cuando *su propio nombre* es una variable. Por ejemplo, digamos que `let miPropiedad = 'sabor'`. Luego `helado[miPropiedad]` nos devolverá `"chocolate"`. Curiosamente, también podemos usarlo cuando creamos objetos: `{ [miPropiedad]: "vainilla" }`. | ||
- **Mutación**: Decimos que un objeto a sido *mutado* cuando alguien cambia para que apunte a un valor diferente. Por ejemplo, si declaramos `let helado = {sabor: "vainilla"}`, podemos después *mutarlo* con `helado.sabor = "chocolate"`. Observa que incluso cuando usamos `const` para declarar `helado`, todavía podremos mutar `helado.sabor`. Esto es porque `const` solo previene asignaciones a la variable `helado`, mientras que lo que nosotros hemos mutado es la *propiedad* (`sabor`) del objeto al que apunta. Algunas personas renuncian a usar 'const' por completo porque les resulta demasiado confuso. | ||
- **Array**: Un array es un objeto que representa una lista de "cosas". Cuando creamos un *literal de array* como `["banana", "chocolate", "vainilla"]`, esencialmente estamos creando un objeto cuya propiedad llamada `0` apunta al valor `"banana"`, la propiedad llamada `1` apunta al valor `"chocolate"`, y la propiedad llamada `2` apunta al valor `"vainilla"`. Sería un rollo escribir `{0: ..., 1: ..., 2: ...}` y por esto mismo es por lo que los arrays son muy útiles. | ||
Hay varias maneras de trabajar con arrays que vienen incorporadas a JavaScript por defecto, como `map`, `filter`, y `reduce`. No desesperes si `reduce` parece muy confuso -- es confuso para cualquiera. | ||
- **Prototipo**: ¿Qué pasa si intentamos acceder a una propiedad que no existe? Por ejemplo, `helado.gusto` (cuando la propiedad en realidad se llama `sabor`). La respuesta es que recibiremos el valor especial `undefined`. Una respuesta más detallada sería que la mayoría de los objetos en JavaScript tienen un "prototipo". Puedes pensar en el prototipo como si fuese una propiedad "escondida" en cada objeto que determina "donde continuar buscando". Así que si no existe la propiedad `gusto` en `helado`, JavaScript buscará la propiedad `gusto` en el prototipo del objeto, después en el prototipo de *este* objeto, y así sucesivamente, y solo retornará `undefined` si llega hasta el final de la "cadena de prototipos" sin encontrar `.gusto`. Es poco común interactuar con este mecanismo directamente, pero explica por qué el objeto `helado` tiene el método `toString` aunque nunca lo hayamos definido nosotros mismos -- es porque viene del prototipo. | ||
|
||
* **Funciones**: Una función es un valor especial que tiene un objetivo concreto: representa *un fragmento de código* del programa. Las funciones son muy útiles para no tener que escribir el mismo código repetidas veces. "Llamar" a una función como `saludo()` le dice al ordenador que ejecute el código que contiene la función y que luego vuelva al mismo punto donde se encontraba antes. Hay muchas maneras de crear una función en JavaScript, con pequeñas diferencias en lo que puede hacer cada una. | ||
- **Argumentos (o Parámetros)**: Los argumentos nos permiten pasar información a la función en el momento en que la llamamos: `saludo("Amelie")`. Dentro de la función, los parámetros actúan como variables. Se les llama "argumentos" o "parámetros" dependiendo de donde nos encontremos (si es donde definimos la función o donde la llamamos). Sin embargo, esta distinción es muy puntillosa, y en la práctica estos términos se usan indistintamente. | ||
- **Expresiones de función**: Previamente, hemos declarado una variable con un valor *cadena de caracteres o string*, como `let mensaje = "Soy una morsa"`. También podemos asignar a una variable una *función*, como `let saludo = function() { }`. Lo que hay después del signo `=` es llamado *Expresiones de función*. Nos devuelve un valor especial (una función) que representa el código que contiene, de esta manera podemos llamar a ese código cuando queramos. | ||
- **Declaración de función**: Es muy cansado escribir algo como `let saludo = function() { }` cada vez que lo necesitemos, por eso podemos usar en su lugar: `function saludo() { }`. Esto se llama *declaración de función*. En lugar de especificar una variable a la izquierda, ponemos el nombre después de la palabra `function`. Estos estilos de declarar una función son casi siempre intercambiables. | ||
- **Alzamiento de funciones o Hoisting**: Normalmente, una variable solo puede ser usada después de declararla con `let` o `const`. Esto puede ser molesto cuando se trata de funciones porque puede que estas se llamen unas a otras, y es difícil rastrear qué función es utilizada por otras y cuales necesitan declararse primero. Por comodidad, cuando (¡y solo cuando!) usemos la sintaxis de *declaración de función*, el orden de las declaraciones no importa porque se "alzan". Esta es una forma elegante de decir que conceptualmente, todas las funciones se trasladan automáticamente a la parte superior del alcance. Así que cuando llamamos a las funciones todas han sido ya declaradas. | ||
- **`this`**: Este es probablemente el concepto más incomprendido en JavaScript, `this` es como un argumento especial en una función. No hace falta pasárselo a la función nosotros mismos, JavaScript lo pasa por nosotros, dependiendo de *como ejecutemos* la función. Por ejemplo, ejecutarla usando la notación por punto `.` -- como en `helado.comer()` -- nos darán un valor `this` especial para lo que haya delante del punto `.` (en el ejemplo, `helado`). El valor de `this` dentro de la función depende de como la función es *llamada*, no de donde es definida. Métodos como `.bind`, `.call`, y `.apply` nos ayudan a tener mas control sobre el valor de `this`. | ||
- **Funciones flecha**: Las funciones flecha son similares a las expresiones de función. Se declaran así: `let saludo = () => { }`. Son muy concisas y normalmente van en una sola línea. Las funciones flecha son *más limitadas* que las funciones regulares -- por ejemplo, no tienen la variable `this`. Cuando escribes `this` dentro de una función flecha, esta usa el `this` de la función regular mas cercana que contenga esta función. Esto es similar a lo que pasa si se utiliza un argumento o una variable que solo existe en una función anterior. Básicamente, esto significa que la gente usa funciones flecha cuando quieren "ver" el mismo `this` dentro de ellas como en el código que las rodea. | ||
- **Enlazado de funciones**: Normalmente, *enlazar* una función `f` a un `this` especifico y a sus argumentos significa crear una *nueva* función que llame a `f` con esos valores predefinidos. JavaScript tiene un método incorporado por defecto llamado `.bind`, pero también se puede hacer "a mano". Enlazar era un método común de hacer que varias funciones "viesen" el mismo `this` que las funciones exteriores. Pero ahora esto se hace con funciones flecha, por lo que ya no se "enlazan" funciones con tanta frecuencia. | ||
- **Pila de llamadas**: Llamar a una función es como entrar a una habitación. Cada vez que llamamos a una función, las variables dentro de ella se inicializan nuevamente. Entonces, cada llamada a la función es como *construir* una nueva "habitación" con su código y entrar en ella. Las variables de nuestra función "viven" en esa habitación. Cuando volvemos de la función, esa "habitación" desaparece con todas sus variables. Podemos visualizar estas habitaciones como una pila vertical de habitaciones: una *pila de llamadas*. Cuando salimos de una función, volvemos a la función "debajo" de la pila de llamadas. | ||
- **Recursión**: Recursión significa que una función se llama a si misma desde su interior. Esto es útil cuando quieres repetir *otra vez* lo que acabas de hacer pero con argumentos diferentes. Por ejemplo, si estás escribiendo un buscador que rastree la web, la función `encuentraLinks(url)` podría primero recolectar todos los links de una pagina, y luego *llamarse a si misma* por cada *link* hasta que visite todas las paginas de esa web. El problema con recursión es que es fácil escribir una función que termine en un loop infinito porque se llama a sí misma continuamente. Si esto ocurre, JavaScript terminara la ejecución de la función con un error de "stack overflow o desbordamiento de pila de llamadas". Se llama así porque hemos hecho muchas llamadas a la misma función en la pila de llamadas, literalmente, desbordándola. | ||
- **Funciones de orden superior o High-order function**: Una función de orden superior es una función que trabaja con otras funciones usándolas como argumentos o devolviéndolas como resultado de su ejecución. Esto puede parecer raro al principio, pero debemos recordar que las funciones son valores que se pueden usar por todo nuestro código -- como hacemos con números, cadenas de caracteres y objetos. Este estilo no debe ser sobreutilizado, pero es muy expresivo si se usa con moderación. | ||
- **Callback**: Realmente Callback no es un término de JavaScript. Es más como un patrón. Es cuando pasamos una función como argumento de otra, esperando que la función que recibe la otra función como argumento la *ejecute después*. De esa manera esperamos un callback o *llamado posterior*. Por ejemplo, `setTimeout` recibe una función como *callback* y... la llama después de que pase un tiempo. No hay nada especial sobre las funciones *callback*. Son funciones normales, así que cuando decimos "callback" en realidad nos referimos a las expectativas que tenemos. | ||
- **Clausura**: Normalmente, cuando una función termina, todas sus variables "desaparecen". Esto ocurre porque ya no se necesitan. ¿Pero qué pasa si declaras una función *dentro* de otra función? Entonces la función de dentro podría ser ejecutada más tarde y podría necesitar acceder/leer las variables de *fuera*, las de la función contenedora. ¡En la práctica, esto es muy útil! Pero para que esto funcione, las variables de la función contenedora necesitan "quedarse por ahí" en algún sitio. Así que en estos casos, JavaScript se encarga de "mantener esas variables vivas" en lugar de "olvidarse" de ellas como haría normalmente. Esto se llama "clausura". Aunque las clausuras son normalmente un concepto bastante incomprendido de las características de JavaScript, probablemente las has utilizado muchas veces sin darte cuenta! | ||
|
||
--- | ||
|
||
JavaScript está hecho de estos conceptos, y muchos más. En mi caso sentía mucha ansiedad en relación a mis conocimientos sobre JavaScript hasta que me formé un mapa mental fuerte sobre todo esto, así pues, me gustaría ayudar a las nuevas generaciones de programadores a superar estas dificultades mas fácilmente. | ||
|
||
Si quieres unirte a mí para sumergirnos mas profundamente en todos estos conceptos, tengo algo que podría interesarte. **[Just JavaScript](https://justjavascript.com/) es mi mapa mental de como JavaScript funciona, y contará con las ilustraciones de la increíble [Maggie Appleton](https://illustrated.dev/)**. Al contrario que este post, va a un ritmo más lento para que pueda ser seguido con más detalle. | ||
|
||
*Just JavaScript* esta dando sus primeros pasos y solo esta disponible por email sin una edición muy cuidada. Si esto te parece interesante, puedes [darte de alta](https://justjavascript.com/) para recibir los borradores por email. Sería de mucha ayuda si me pudieses dar tu opinión. Muchas gracias! |