Herramientas de usuario

Herramientas del sitio


informatica:programacion:cursos:programacion_avanzada_javascript:otras_caracteristicas_ecmascript

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
informatica:programacion:cursos:programacion_avanzada_javascript:otras_caracteristicas_ecmascript [2024/10/29 16:15] – [Cortocircuito de expresiones] tempwininformatica:programacion:cursos:programacion_avanzada_javascript:otras_caracteristicas_ecmascript [2024/10/30 13:13] (actual) – [Paréntesis obligatorios] tempwin
Línea 185: Línea 185:
 El resultado es que **se produce un error**: ''Unexpected token ??'': El resultado es que **se produce un error**: ''Unexpected token ??'':
  
-<WRAP center round todo 60%> +{{ :informatica:programacion:cursos:programacion_avanzada_javascript:22-null-coalescing-error.png |}}
-El error que se produce +
-</WRAP>+
  
 El motivo es que, al combinar este tipo de operadores, hagas lo que hagas con la precedencia no puedes evitar que la interpretación que hace el programador de lo que está escribiendo entre en conflicto con lo que el diseñador del lenguaje haya decidido. Por ejemplo, en el fragmento anterior, eso se puede interpretar como: El motivo es que, al combinar este tipo de operadores, hagas lo que hagas con la precedencia no puedes evitar que la interpretación que hace el programador de lo que está escribiendo entre en conflicto con lo que el diseñador del lenguaje haya decidido. Por ejemplo, en el fragmento anterior, eso se puede interpretar como:
Línea 210: Línea 208:
 ===== El operador de encadenamiento opcional: evitando errores por nulos ===== ===== El operador de encadenamiento opcional: evitando errores por nulos =====
  
-El operador de encadenamiento opcional, ?. apareció con ECMAScript 2020 y nos permite simplificar enormemente las expresiones con propiedades o arrays que podrían tener valores nulos.+El operador de encadenamiento opcional, ''?.'' apareció con ECMAScript 2020 y nos permite simplificar enormemente las expresiones con propiedades o arrays que podrían tener valores nulos.
  
 Un caso habitual es el siguiente: estamos accediendo a un servicio que nos devuelve información de objetos que necesitamos para nuestra aplicación. Estos objetos pueden tener a su vez varios subobjetos a los que necesitamos acceder para hacer cosas, por ejemplo: Un caso habitual es el siguiente: estamos accediendo a un servicio que nos devuelve información de objetos que necesitamos para nuestra aplicación. Estos objetos pueden tener a su vez varios subobjetos a los que necesitamos acceder para hacer cosas, por ejemplo:
  
 +<code javascript>
 if (usuario.direccion.planta.length > 0) { if (usuario.direccion.planta.length > 0) {
  //lo que sea...  //lo que sea...
 } }
 +</code>
  
-El problema de lo anterior es que es posible que el usuario no tenga dirección, y si la tiene quizá no tiene el campo de la planta en la que vive (porque es una casa unifamiliar, por ejemplo). Por lo que la expresión anterior no se puede utilizar ya que cualquier punto de la cadena de propiedades puede ser nulo y fallar. Por ello, en estos casos se suele escribir algo como esto cuando usamos JavaScript "clásico" (ECMAScript 5):+El problema de lo anterior es que es posible que el usuario no tenga dirección, y si la tiene quizá no tiene el campo de la planta en la que vive (porque es una casa unifamiliar, por ejemplo). Por lo que la expresión anterior no se puede utilizar ya que **cualquier punto de la cadena de propiedades puede ser nulo y fallar**. Por ello, en estos casos se suele escribir algo como esto cuando usamos JavaScript "clásico" (ECMAScript 5):
  
 +<code javascript>
 if (usuario && usuario.direccion && usuario.direccion.planta) { if (usuario && usuario.direccion && usuario.direccion.planta) {
     if (usuario.direccion.planta.length > 0) {     if (usuario.direccion.planta.length > 0) {
Línea 225: Línea 226:
  }  }
 } }
 +</code>
  
 Es decir, antes de poder utilizar nuestra expresión original debemos comprobar que todos los elementos de la cadena de propiedades existen (no son nulos), para asegurarnos de que no se produce un error. Es decir, antes de poder utilizar nuestra expresión original debemos comprobar que todos los elementos de la cadena de propiedades existen (no son nulos), para asegurarnos de que no se produce un error.
  
-    Obviamente sólo es necesario comprobar aquellos que puedan estar nulos. Por ejemplo, su el usuario siempre va a existir como resultado de la llamada al servicio (o sea, el servicio no nos va a devolver nunca un nulo), la primera comprobación (if (usuario)) no es necesaria.+<WRAP center round tip 60%> 
 +Obviamente sólo es necesario comprobar aquellos que puedan estar nulos. Por ejemplo, su el usuario siempre va a existir como resultado de la llamada al servicio (o sea, el servicio no nos va a devolver nunca un nulo), la primera comprobación (''if (usuario)'') no es necesaria. 
 +</WRAP>
  
-Lo anterior funciona porque el operador AND (&&) tiene cortocircuito de expresiones, es decir, dado que para ser cierto ambas partes de la comparación deben ser ciertas, en cuanto la primera no lo es ya no se comprueba la segunda, por lo que en cuanto cualquier parte de la cadena de propiedades se encuentra un nulo, no se evalúan las demás, y no se produce nunca un error por nulos.+Lo anterior funciona porque el operador AND (''&&'') tiene cortocircuito de expresiones, es decir, dado que para ser cierto ambas partes de la comparación deben ser ciertas, en cuanto la primera no lo es ya no se comprueba la segunda, por lo que en cuanto cualquier parte de la cadena de propiedades se encuentra un nulo, no se evalúan las demás, y no se produce nunca un error por nulos.
  
-Este tipo de expresiones es muy habitual verlas por ahí y funcionan bien, pero son tediosas de escribir, largas y no contribuyen precisamente a la claridad del código.+Este tipo de expresiones es muy habitual verlas por ahí y funcionan bien, pero **son tediosas de escribir, largas y no contribuyen precisamente a la claridad del código**.
  
 Por suerte, ECMAScript nos proporciona un elemento específico para facilitarnos la vida: el operador de encadenamiento opcional: ?.. Gracias a él podemos escribir esto: Por suerte, ECMAScript nos proporciona un elemento específico para facilitarnos la vida: el operador de encadenamiento opcional: ?.. Gracias a él podemos escribir esto:
  
 +<code javascript>
 if (usuario?.direccion?.planta?.length > 0) { if (usuario?.direccion?.planta?.length > 0) {
  //lo que sea...  //lo que sea...
 } }
 +</code>
  
-Es decir, al ponerlo delante de una propiedad, ésta sólo se evalúa si el objeto precedente no es nulo ni undefined (o no es "nuloso", o sea, algo que el lenguaje interpreta como nulo).+Es decir, al ponerlo delante de una propiedad, ésta **sólo se evalúa si el objeto precedente no es nulo ni ''undefined''** (o no es "nuloso", o sea, algo que el lenguaje interpreta como nulo).
  
-Lo que se obtiene en caso de que algún punto de la cadena sea nulo o no definido es un valor no definido, o sea undefined.+Lo que se obtiene en caso de que algún punto de la cadena sea nulo o no definido es **un valor no definido**, o sea ''undefined''.
  
-Esto es equivalente a usar todos aquellos && de antes, pero mucho más claro de leer y sobre todo de escribir.+Esto es equivalente a usar todos aquellos ''&&'' de antes, pero **mucho más claro de leer y sobre todo de escribir**.
  
-    MUY IMPORTANTE: el primer objeto de la cadena debe existir y estar definido, ya que el operador necesita al menos un objeto "padre" inicial del que partir. Es decir, en nuestro ejemplo, usuario debe existir, estar definido y no ser nulo. Si se obtiene como resultado de una llamada a un servicio, por ejemplo, debemos recibir algo, aunque sea un objeto vacío, un número o lo que sea, si no recibiremos un error.+<WRAP center round important 60%> 
 +MUY IMPORTANTE: el primer objeto de la cadena debe existir y estar definido, ya que el operador necesita al menos un objeto "padre" inicial del que partir. Es decir, en nuestro ejemplo, ''usuario'' debe existir, estar definido y no ser nulo. Si se obtiene como resultado de una llamada a un servicio, por ejemplo, debemos recibir algo, aunque sea un objeto vacío, un número o lo que sea, si no recibiremos un error. 
 +</WRAP>
  
-Llamadas a funciones+==== Llamadas a funciones ====
  
-Pero este operador sirve para más cosas que simplemente encadenar propiedades de objetos. También es posible utilizarlo para hacer llamadas a funciones, sólo si la función está definida. Por ejemplo:+Pero este operador sirve para más cosas que simplemente encadenar propiedades de objetos. También es posible utilizarlo para hacer **llamadas a funciones, sólo si la función está definida**. Por ejemplo:
  
 +<code javascript>
 var res = usuario?.haceralgo?.(); var res = usuario?.haceralgo?.();
 +</code>
  
-Esta sintaxis tan rara, ?.() lo que quiere decir es que, si está definida la función, llámala, y si no lo está, devuelve un undefined. De este modo podemos crear interfaces que tengan miembros opcionales, que sólo se implementan según ciertas condiciones, o podemos llamar a diferentes versiones de una API sin que rompa todo en caso de que un método no esté implementado. Muy útil.+Esta sintaxis tan rara, ''?.()'' lo que quiere decir es que, si está definida la función, llámala, y si no lo está, devuelve un ''undefined''. De este modo podemos crear interfaces que tengan miembros opcionales, que sólo se implementan según ciertas condiciones, o podemos llamar a diferentes versiones de una API sin que rompa todo en caso de que un método no esté implementado. Muy útil.
  
-Es importante señalar que si el supuesto método existe pero no es un método, se producirá un error de tipos. Es decir, lo anterior funciona si el miembro que queremos llamar no existe. Pero, en nuestro ejemplo, si usuario.hazAlgo existe y es otra cosa que no es una función (por ejemplo un array o una simple propiedad) se producirá un TypeError. Esto es una buena política porque sino podrían darse otros errores diferentes. De este modo tenemos que ser conscientes que vamos a llamar a una posible función. +Es importante señalar que si el supuesto método existe pero no es un método, se producirá un error de tipos. Es decir, lo anterior funciona si el miembro que queremos llamar no existe. Pero, en nuestro ejemplo, si ''usuario.hazAlgo'' existe y es otra cosa que no es una función (por ejemplo un array o una simple propiedad) se producirá un ''TypeError''. Esto es una buena política porque sino podrían darse otros errores diferentes. De este modo tenemos que ser conscientes que vamos a llamar a una posible función. 
-Cortocircuito de expresiones+ 
 +==== Cortocircuito de expresiones ====
  
 Este operador también incluye cortocircuito de expresiones. Es decir, que en cuanto se encuentra un eslabón de la cadena que es nulo o no definido, no sigue evaluando los demás. Así, por ejemplo: Este operador también incluye cortocircuito de expresiones. Es decir, que en cuanto se encuentra un eslabón de la cadena que es nulo o no definido, no sigue evaluando los demás. Así, por ejemplo:
  
 +<code javascript>
 var n = 0; var n = 0;
 var res = usuario?.haceralgo?.(n++); var res = usuario?.haceralgo?.(n++);
 +</code>
  
-...si el usuario o si la función hacerAlgo no existe y por tanto no se ejecuta, la variable n tampoco aumenta de valor ya que se detiene la evaluación de la expresión posterior a ella. +...si el usuario o si la función ''hacerAlgo'' no existe y por tanto no se ejecuta, la variable n tampoco aumenta de valor ya que se detiene la evaluación de la expresión posterior a ella.
-Acceso a arrays+
  
-En JavaScript una alternativa la sintaxis . para acceder a una propiedad es mediante indexación por nombre, así:+==== Acceso arrays ====
  
 +En JavaScript una alternativa a la sintaxis ''.'' para acceder a una propiedad es mediante indexación por nombre, así:
 +
 +<code javascript>
 var color = usuario.ajustes['color']; var color = usuario.ajustes['color'];
 +</code>
  
 que es equivalente a: que es equivalente a:
  
 +<code javascript>
 var color = usuario.ajustes.color; var color = usuario.ajustes.color;
 +</code>
  
 La ventaja de la primera sintaxis es que nos permite decidir el nombre de la propiedad dinámicamente, es decir, no va escrita en el código sino que que podemos recibirla en una variable: La ventaja de la primera sintaxis es que nos permite decidir el nombre de la propiedad dinámicamente, es decir, no va escrita en el código sino que que podemos recibirla en una variable:
  
 +<code javascript>
 var nomAjuste = obtenerNombreAjusteColor(); //De un servicio por ejemplo, devuelve 'color' var nomAjuste = obtenerNombreAjusteColor(); //De un servicio por ejemplo, devuelve 'color'
 var color = usuario.ajustes.[nomAjuste]; var color = usuario.ajustes.[nomAjuste];
 +</code>
  
 cosa que no podríamos hacer con la sintaxis habitual del punto. cosa que no podríamos hacer con la sintaxis habitual del punto.
  
-En este caso, si la propiedad es nula o no está definida JavaScript devuelve un error. O sea, en este ejemplo si el servicio nos devuelve un null en la propiedad ajustes o si directamente no la define, se produciría un error.+En este caso, si la propiedad es nula o no está definida JavaScript devuelve un error. O sea, en este ejemplo si el servicio nos devuelve un ''null'' en la propiedad ''ajustes'' o si directamente no la define, se produciría un error.
  
-Para facilitar este caso, una tercera sintaxis de este operador nos permite acceder al contenido de arrays o colecciones aunque sean nulas o no estén definidas:+Para facilitar este caso, una tercera sintaxis de este operador nos permite **acceder al contenido de arrays o colecciones aunque sean nulas o no estén definidas**:
  
 +<code javascript>
 var color = usuario?.ajustes?.['color'].valor; var color = usuario?.ajustes?.['color'].valor;
 +</code>
  
-En este caso está intentando acceder a las propiedades del objeto ajustes por su nombre.+En este caso está intentando acceder a las propiedades del objeto ''ajustes'' por su nombre.
  
-Fíjate además que, por el cortocircuito de expresiones, si ajustes es nulo o no está definido se devuelve un undefined y ya no se intenta leer la propiedad valor del resultado tampoco (de todos modos si creemos que ajustes puede existir pero el ajuste en concreto no, convendría usar ?. también con esta última propiedad, claro).+Fíjate además que, por el cortocircuito de expresiones, si ''ajustes'' es nulo o no está definido se devuelve un ''undefined'' y ya no se intenta leer la propiedad ''valor'' del resultado tampoco (de todos modos si creemos que ''ajustes'' puede existir pero el ajuste en concreto no, convendría usar ''?.'' también con esta última propiedad, claro).
  
 Nos vale también para arrays normales y corrientes accedidas mediante índice: Nos vale también para arrays normales y corrientes accedidas mediante índice:
  
 +<code javascript>
 var color = usuario?.ajustes?.[0]; var color = usuario?.ajustes?.[0];
 +</code>
  
-De este modo si ajustes no está definido o es nulo no se producirá un error, como sí ocurriría sin este operador. +De este modo si ''ajustes'' no está definido o es nulo no se producirá un error, como sí ocurriría sin este operador. 
-Devolver algo diferente a no definido+ 
 +==== Devolver algo diferente a no definido ====
  
 Finalmente, podemos combinar ese nuevo operador con el operador de unión "nulosa", que ya conocemos, para devolver un valor por defecto en estos casos, así: Finalmente, podemos combinar ese nuevo operador con el operador de unión "nulosa", que ya conocemos, para devolver un valor por defecto en estos casos, así:
  
 +<code javascript>
 var color = usuario?.ajustes?.['color'].valor ?? "#fff"; var color = usuario?.ajustes?.['color'].valor ?? "#fff";
 +</code>
  
 que en caso de no estar definido devolvería un color por defecto (el color blanco). que en caso de no estar definido devolvería un color por defecto (el color blanco).
-En resumen 
  
-El operador ?. es muy útil para escribir expresiones concisas y legibles sin arriesgarnos a que un valor nulo o no definido provoque un error en nuestro código. Su uso es extremadamente sencillo y sólo hay que conocer los pequeños detalles asociados que se explican en esta lección.+==== En resumen ==== 
 + 
 +El operador ''?.'' es muy útil para escribir expresiones concisas y legibles sin arriesgarnos a que un valor nulo o no definido provoque un error en nuestro código. Su uso es extremadamente sencillo y sólo hay que conocer los pequeños detalles asociados que se explican en esta lección.
  
-El soporte de este operador es total en los navegadores evergreen, o sea, en todos los actuales (Chrome, Firefox, Opera, Safari, Brave...), así que podemos usarlo sin miedo salvo que tengamos que dar soporte a versiones antiguas o a Internet Explorer por algún motivo.+El soporte de este operador es total en los navegadores //evergreen//, o sea, en todos los actuales (Chrome, Firefox, Opera, Safari, Brave...), así que podemos usarlo sin miedo salvo que tengamos que dar soporte a versiones antiguas o a Internet Explorer por algún motivo.
informatica/programacion/cursos/programacion_avanzada_javascript/otras_caracteristicas_ecmascript.1730214936.txt.gz · Última modificación: por tempwin