From e96bb5bd4aa2ffde1314037685e011b58eef80a8 Mon Sep 17 00:00:00 2001 From: vplentinax Date: Thu, 14 May 2020 16:40:19 -0400 Subject: [PATCH 1/9] optional-chaining --- .../07-optional-chaining/article.md | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 1-js/04-object-basics/07-optional-chaining/article.md diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md new file mode 100644 index 000000000..1922aa0c4 --- /dev/null +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -0,0 +1,176 @@ + +# Encadenamiento opcional '?.' + +[recent browser="new"] + +El encadenamiento opcional `?.` es una forma a prueba de errores para acceder a las propiedades de los objetos anidados, incluso si no existe una propiedad intermedia. + +## El problema + +Si acaba de comenzar a leer el tutorial y aprender JavaScript, quizás el problema aún no lo haya tocado, pero es bastante común. + +Por ejemplo, algunos de nuestros usuarios tienen direcciones, pero pocos no las proporcionaron. Entonces no podemos leer con seguridad `user.address.street`: + +```js run +let user = {}; // el usuario pasa a estar sin dirección + +alert(user.address.street); // Error! +``` + +O, en el desarrollo web, nos gustaría obtener información sobre un elemento en la página, pero puede no existir: + +```js run +// Error si el resultado de querySelector (...) es nulo +let html = document.querySelector('.my-element').innerHTML; +``` + +Antes de que apareciera `?.` en el lenguaje, el operador `&&` se usaba para solucionarlo. + +Por ejemplo: + +```js run +let user = {}; // El usuario no tiene dirección + +alert( user && user.address && user.address.street ); // undefined (no error) +``` + +Y el camino completo a la propiedad asegura que todos los componentes existen, pero es engorroso de escribir. + +## Encadenamiento opcional + +El encadenamiento opcional `?.` detiene la evaluación y devuelve` undefined` si la parte anterior a `?.` es` undefined` o `null`. + +Más adelante en este artículo, por brevedad, diremos que algo "existe" si no es `null` ni `undefined`. + + +Aquí está la forma segura de acceder a `user.address.street`: + +```js run +let user = {}; // El usuario no tiene dirección + +alert( user?.address?.street ); // undefined (no error) +``` + +Leer la dirección con `user? .Address` funciona incluso si el objeto `user` no existe: + +```js run +let user = null; + +alert( user?.address ); // undefined + +alert( user?.address.street ); // undefined +alert( user?.address.street.anything ); // undefined +``` + +Tenga en cuenta: la sintaxis `?.` funciona exactamente donde está colocada, nada más. + +En las últimas dos líneas, la evaluación se detiene inmediatamente después de `user?.`, sin acceder nunca a otras propiedades. Pero si `user` realmente existe, entonces las propiedades intermedias adicionales, como `user.address`deben existir. + +```warn header="No abuses del encadenamiento opcional" +Deberíamos usar `?.` solo donde está bien que algo no exista. + +Por ejemplo, si de acuerdo con nuestra lógica de codificación, el objeto `user` debe estar allí, pero `address` es opcional, entonces `user.address?.Street` sería mejor. + +Entonces, si `user` no está definido debido a un error, lo sabremos y lo arreglaremos. De lo contrario, los errores de codificación pueden silenciarse donde no sea apropiado y volverse más difíciles de depurar. +``` + +````warn header="La variable antes de `?.` debe existir" +Si no hay una variable `user`, entonces `user? .Anything` provocará un error: + +```js run +// ReferenceError: El usuario no está definido +user?.address; +``` +El encadenamiento opcional solo prueba para `null/undefined`, no interfiere con ninguna otra mecánica del lenguaje. +```` + +## Short-circuiting (Cortocircuitos) + +Como se dijo antes, el `?.` detiene inmediatamente ("cotocircuito") la evaluación si la parte izquierda no existe. + +Entonces, si hay más llamadas a funciones o efectos secundarios, estos no suceden: + +```js run +let user = null; +let x = 0; + +user?.sayHi(x++); // no pasa nada + +alert(x); // 0, el valor no se incrementa +``` + +## Otros casos: ?.(), ?.[ ] + +El encadenamiento opcional `?.` no es un operador, sino una construcción de sintaxis especial, que también funciona con funciones y corchetes. + +Por ejemplo, `?.()` Se usa para llamar a una función que puede no existir. + +En el siguiente código, algunos de nuestros usuarios tienen el método `admin`, y otros no: + +```js run +let user1 = { + admin() { + alert("I am admin"); + } +} + +let user2 = {}; + +*!* +user1.admin?.(); // I am admin +user2.admin?.(); +*/!* +``` + +Aquí, en ambas líneas, primero usamos el punto `.` para obtener la propiedad `admin`, porque el objeto usuario debe existir, por lo que es seguro leerlo. + +Entonces `?.()` Comprueba la parte izquierda: si el usuario existe, entonces se ejecuta (para `user1`). De lo contrario (para `user2`) la evaluación se detiene sin errores. + +La sintaxis `?.[]` también funciona, si nos gustaría usar corchetes `[]` para acceder a las propiedades en lugar de punto `.`. Al igual que en casos anteriores, permite leer de forma segura una propiedad de un objeto que puede no existir. + +```js run +let user1 = { + firstName: "John" +}; + +let user2 = null; // Imagine, no podríamos autorizar al usuario + +let key = "firstName"; + +alert( user1?.[key] ); // John +alert( user2?.[key] ); // undefined + +alert( user1?.[key]?.something?.not?.existing); // undefined +``` + +También podemos usar `?.` con `delete`: + +```js run +delete user?.name; // Eliminar user.name si el usuario existe +``` + +```warn header="Podemos usar `?.` para una lectura y eliminación segura, pero no para escribir" +El encadenamiento opcional `?.` no tiene uso en el lado izquierdo de una tarea: + +```js run +// la idea del siguiente código es escribir user.name, si el usuario existe + +user?.name = "John"; // Error, no funciona +// porque se evalúa como undefined = "John" +``` + +## Resumen + +La sintaxis `?.` tiene tres formas: + +1. `obj?.prop` -- devuelve `obj.prop` si `obj` existe, sino `undefined`. +2. `obj?.[prop]` -- devuelve `obj[prop]` si `obj` existe, sino `undefined`. +3. `obj?.method()` -- llama a `obj.method()` si `obj` existe, sino devuelve `undefined`. + +Como podemos ver, todos ellos son sencillos y fáciles de usar. El `?.` comprueba la parte izquierda para `null/undefined` y permite que la evaluación continúe si no es así. + +Una cadena de `?.` permite acceder de forma segura a las propiedades anidadas. + +Aún así, debemos aplicar `?.` con cuidado, solo donde está bien que la parte izquierda no exista. + +Para que no nos oculte errores de programación, si ocurren. From a72b21b84a8688c61f854d118d0b338c13350cf7 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:23:44 -0400 Subject: [PATCH 2/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 70eddfe83..9e22c5f36 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -98,7 +98,7 @@ user?.sayHi(x++); // no pasa nada alert(x); // 0, el valor no se incrementa ``` -## Otros casos: ?.(), ?.[ ] +## Otros casos: ?.(), ?.[] El encadenamiento opcional `?.` no es un operador, sino una construcción de sintaxis especial, que también funciona con funciones y corchetes. @@ -171,4 +171,3 @@ Una cadena de `?.` permite acceder de forma segura a las propiedades anidadas. Aún así, debemos aplicar `?.` con cuidado, solo donde está bien que la parte izquierda no exista. Para que no nos oculte errores de programación, si ocurren. - From 7a549306d26544ac07d9a4fdd8837b8077fc7913 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:23:52 -0400 Subject: [PATCH 3/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 9e22c5f36..3ec2f4a3a 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -12,7 +12,7 @@ Si acaba de comenzar a leer el tutorial y aprender JavaScript, quizás el proble Por ejemplo, algunos de nuestros usuarios tienen direcciones, pero pocos no las proporcionaron. Entonces no podemos leer con seguridad `user.address.street`: ```js run -let user = {}; // el usuario pasa a estar sin dirección +let user = {}; // usuario sin dirección alert(user.address.street); // Error! ``` From 348c258c154599ed06ffab61caea850d6833031e Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:24:00 -0400 Subject: [PATCH 4/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 1 + 1 file changed, 1 insertion(+) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 3ec2f4a3a..c9c451c77 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -47,6 +47,7 @@ Aquí está la forma segura de acceder a `user.address.street`: ```js run let user = {}; // El usuario no tiene dirección + alert( user?.address?.street ); // undefined (no error) ``` From 48f60c271eb8702568527abfe591ced8f182dcf5 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:24:11 -0400 Subject: [PATCH 5/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index c9c451c77..00f3eb119 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -126,7 +126,7 @@ Aquí, en ambas líneas, primero usamos el punto `.` para obtener la propiedad ` Entonces `?.()` Comprueba la parte izquierda: si el usuario existe, entonces se ejecuta (para `user1`). De lo contrario (para `user2`) la evaluación se detiene sin errores. -La sintaxis `?.[]` también funciona, si nos gustaría usar corchetes `[]` para acceder a las propiedades en lugar de punto `.`. Al igual que en casos anteriores, permite leer de forma segura una propiedad de un objeto que puede no existir. +La sintaxis `?.[]` también funciona si quisiéramos usar corchetes `[]` para acceder a las propiedades en lugar de punto `.`. Al igual que en casos anteriores, permite leer de forma segura una propiedad de un objeto que puede no existir. ```js run let user1 = { From 76de5bba307bad41bda8a07ebc691f309c910c8a Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:24:18 -0400 Subject: [PATCH 6/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 00f3eb119..c398df25c 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -132,7 +132,9 @@ La sintaxis `?.[]` también funciona si quisiéramos usar corchetes `[]` para ac let user1 = { firstName: "John" }; + let user2 = null; // Imagine, no podríamos autorizar al usuario + let key = "firstName"; alert( user1?.[key] ); // John From 2f1a6e58f3a05e91143a43aea1e47190d8a33fa3 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:24:24 -0400 Subject: [PATCH 7/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index c398df25c..26ecbf6f8 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -163,7 +163,7 @@ user?.name = "John"; // Error, no funciona La sintaxis `?.` tiene tres formas: -1. `obj?.prop` -- devuelve `obj.prop` si `obj` existe, sino `undefined`. +1. `obj?.prop` -- devuelve `obj.prop` si `obj` existe, si no, `undefined`. 2. `obj?.[prop]` -- devuelve `obj[prop]` si `obj` existe, sino `undefined`. 3. `obj?.method()` -- llama a `obj.method()` si `obj` existe, sino devuelve `undefined`. From 3bf37d3381605b5a6db1138cdf680da97f239dce Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:24:40 -0400 Subject: [PATCH 8/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 26ecbf6f8..7e056c891 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -164,7 +164,7 @@ user?.name = "John"; // Error, no funciona La sintaxis `?.` tiene tres formas: 1. `obj?.prop` -- devuelve `obj.prop` si `obj` existe, si no, `undefined`. -2. `obj?.[prop]` -- devuelve `obj[prop]` si `obj` existe, sino `undefined`. +2. `obj?.[prop]` -- devuelve `obj[prop]` si `obj` existe, si no, `undefined`. 3. `obj?.method()` -- llama a `obj.method()` si `obj` existe, sino devuelve `undefined`. Como podemos ver, todos ellos son sencillos y fáciles de usar. El `?.` comprueba la parte izquierda para `null/undefined` y permite que la evaluación continúe si no es así. From f1cb7da39ef0a44b7dc5b8b1f2ede349d8e9dfab Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:24:49 -0400 Subject: [PATCH 9/9] Update 1-js/04-object-basics/07-optional-chaining/article.md Co-authored-by: joaquinelio --- 1-js/04-object-basics/07-optional-chaining/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 7e056c891..06bbe6771 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -165,7 +165,7 @@ La sintaxis `?.` tiene tres formas: 1. `obj?.prop` -- devuelve `obj.prop` si `obj` existe, si no, `undefined`. 2. `obj?.[prop]` -- devuelve `obj[prop]` si `obj` existe, si no, `undefined`. -3. `obj?.method()` -- llama a `obj.method()` si `obj` existe, sino devuelve `undefined`. +3. `obj?.method()` -- llama a `obj.method()` si `obj` existe, si no devuelve `undefined`. Como podemos ver, todos ellos son sencillos y fáciles de usar. El `?.` comprueba la parte izquierda para `null/undefined` y permite que la evaluación continúe si no es así.