Las funciones setInterval() y setTimeout() en javascript.

Feliz 2017 a todos, esta es la primera entrada del año. Una cuestión sencilla de javascript ¿para qué valen las funciones setInterval() y setTimeout() y en qué se diferencian?

Pues ambas funciones tienen el mismo objetivo: ejecutar otra función pasado un intervalo de tiempo. ¿En qué se diferencian? En que setTimeout() se ejecutará solamente una vez, mientras que setInterval() lo hará en repetidas ocasiones.

Por ejemplo, podríamos usar setInterval() para que se mostrara en pantalla cuántos segundos llevamos desde que se cargó la página:

/*definimos una función que cada ponga en un
cuadro de texto un valor numérico, sumando uno cada
vez que la invocamos*/
function showSeconds(){
 var val = document.getElementById("tiempo").value;
 document.getElementById("tiempo").value = parseInt(val)+1;
}
/*usamos setTimeout() para que se
ejecute cada segundo (1000 milisegundos como parámetro)*/
setInterval(showSeconds,1000);

O podríamos usar setTimeout() para dar un aviso al usuario a los diez segundos de entrar

/*función que sólo hace un alert*/
function funcAvisa(){
 window.alert("Pareces interesado en esta sección");
}
/*se la llama a los 10 segundos*/
setTimeout(funcAvisa,10000);

Así funcionan los dos temporizadores de Javascript.

Declarar una función en Javascript

Hemos hablado mucho de javascript en este blog, pero a veces nos dejamos por explicar cosas básicas ¿Cómo se declara una función? y ya puestos ¿para qué sirve hacerlo?

Bueno, la utilidad de una función es no tener que repetir el mismo bloque de código varias veces. Nos permite agrupar externamente una serie de instrucciones para luego llamarla desde cualquier parte del código.

Para declarar una función debemos usar la palabra reservada function. Tras ella, separada por un espacio, ponemos el nombre que queremos darle seguido de los párametros que recibirá ,si es que recibe alguno, que pondremos entre paréntesis. Abriremos unas llaves y dentro insertaremos el código de la función. Si la función debe devolver un valor esto lo definiremos con la palabra return, que además finalizará la función. Vamos con un ejemplo práctico, una función que calcula un precio final aplicándole unos valores fijos al que recibe:

function precioFinal(precio,descuento){
  var ivaCultural = 1.21;
  var gastosEnvio = 10;
  var precioFinal = (precio*ivaCultural*(100-descuento/100))+10;
  return precioFinal.toFixed(2);
}

La función recibiría un precio y un descuento en porcentaje, le añadiría el IVA, le aplicaría el descuento, le sumaria los gastos de envío y devolvería el resultado rendondeado a dos decimales. En el código llamaríamos así a la función:

var precio = precioFinal(449.99,10);

Como el intérprete de javascript de los navegadores busca en primer lugar la declaración de variables y de funciones una función puede aparecer en el código antes de ser declarada.

Javascript: mostrar número con decimales en formato de moneda.

Seguro que más de una vez has estado trabajando con Javascript y has necesitado calcular un importe monetario. Y seguro que más de una vez a aplicar un descuento porcentual te ha salido un churro con 7 decimales (aprox) ¿Cómo se puede solucionar esto? pues con el método toFixed().

El método toFixed() existe de Javascript 1.5, se puede aplicar sobre todos los objetos numéricos y devuelve una cadena con el número seguido de tantos decimales como le pasemos a la función como parámetro. Si la cantidad de decimales que queremos es menor que la del número al que aplicamos el método realizará una operación de redondeo, en caso de que sea mayor entonces rellenará con ceros. Si no le pasamos ningún número como parámetro entonces redondeará a entero.

var n = 5.56998767123;
var num1 = n.toFixed();
var num2 = n.toFixed(3);
var num3 = n.toFixed(2);

//num1 tendrá el valor 6
//num2 tendrá el valor 5.570
//num3 tendrá el valor 5.57

Por tanto, si necesitas un formato monetario te basta con un .toFixed(2) para mostrar sólo dos decimales.

Definir el ancho y el alto de un iframe con Javascript

Una entrada rápida ¿cómo definimos el alto y el ancho de un iframe con Javascript? Pues sirviéndonos de sus propiedades width y height:

//ejemplo: definimos iFrame con
//600px de alto y 800 de ancho
document.getElementById("miIFrame").height = "600";
document.getElementById("miIFrame").width= "800";

Basta con pasarle el valor en píxeles del tamaño que queremos darle en forma de cadena.

jQuery: pulsar F11 y evitar entrar en modo pantalla completa

Un cliente tenía una petición curiosa: quería que su web mostrara un menú al pulsar la tecla F11 (habían migrado de una aplicación de escritorio a una web y estaban acostumbrados a pulsar F11 y que saliera eso) ¿Qué ocurre? Pues que F11 es la tecla que activa el modo a pantalla completa del navegador.

¿Se puede hacer esto? Sí, tenía mis dudas pero sí. Tenía mis dudas porque las teclas de función no siempre pueden sobreescribirse para limitar el comportamiento del navegador (por ejemplo, creo que con F5 o con F1 no sería posible). Pero F11, al menos en IE10, Chrome y Firefox sí puede ser deshabilitada. Os dejo el código, es javascript usando la librería jQuery:

$(document).keydown(function(event) {
  event.preventDefault();
    if (event.keyCode == 122) { // 122 es el código de F11
      event.originalEvent.keyCode = 0;
      window.alert("no dejo maximizar");
    }
});

Lógicamente, en lugar del window.alert ahí ya pondríais el código que queráis ejecutar en vuestra aplicación web.

Javascript: convertir los saltos de línea de un textárea en un salto de línea html.

Se daba el caso hoy de que tenía que recoger el texto extraído de un textarea, mediante javascript, y mostrarlo dentro de un div al pulsar un botón en pantalla. ¿Y qué problema había? Que los saltos de línea desaparecían. ¿Cómo se puede solucionar? De dos formas: Hay con vertir el caracter ASCII(10), que se representa con el símbolo \n en una etiqueta br, o como otra opción meter el texto entre etiquetas pre para que sea interpretado por el navegador como texto preformateado. Veamos el ejemplo:

//usando jQuery
var texto = $('#idDelTextarea').val();
texto = texto.replace(/\n/g, "<br />");
$("#idDelDiv").html(texto);

//sin jQuery
var texto = document.getElementById("idDelTextarea").value;
texto = texto.replace(/\n/g, "<br />");
document.getElementById("idDelDiv").innerHtml = texto;

//con <pre>
//recogemos el texto con alguno de los métodos anteriores
texto = "<pre>" + texto + "</pre>";
//y lo metemos en el div

ECMAScript 6: Funciones flecha gruesa

Seguimos la serie de artículos dedicados a ECMAScript 6, en este caso con las funciones arrow, funciones flecha o funciones de flecha gruesa. Esta novedad consiste en una sintaxis abreviada para la expresión de función. Además vinculan el valor this contextualmente.

La cuestión de la sintaxist abreviada es simple si vemos un ejemplo:

var a = [
  "Peras",
  "Manzanas",
  "Naranjas",
  "Melones"
];

//Sintaxis de toda la vida
var a2 = a.map(function(t){ return t.length });

//Sintaxis con flecha
var a2 = a.map( s => s.length );

El tema del this contextual es algo más complejo. Seguramente recuerdes que la variable this daba a veces muchos dolores de cabeza ya que pertenecía sólo a un contexto, es decir, cada función definía su propio valor de this. Vamos con un ejemplo de como sería el código old-school:

function Miembro() {
   // Este this es una instancia del constructor Miembro()
   this.experiencia = 0;
   setInterval(function aprender() {
      // Y este this de debajo sería
      //una instancia de la función aprender(),
      //por tanto no podemos usarlo fuera de
      //la función de callback
      //y nos podría generar errores
      this.experiencia++;
   }, 5000);
} 

Teníais la opción de cachear el this dentro de una variable:

function Miembro() {
   var that = this;
   that.experiencia = 0;
   setInterval(function aprender() {
      // Y este this de debajo sería
      //una instancia de la función aprender(),
      //por tanto no podemos usarlo fuera de
      //la función de callback
      that.experiencia++;
   }, 5000);
} 

Otra opción era usar la función bind() para vincular dicha función a this.

Pero con la función de flecha gruesa la cosa es mucho más simple:

function Miembro(){
  this.experiencia = 0;
  //y aquí va la magiar!!!!
  setInterval(() => {
    this.aexperiencia++; //no es un this nuevo, sino que
                       //hace referencia al this de Miembro()
  }, 5000);
}

ECMAScript 6: valores por defecto en las funciones Javascript

Muchos lenguajes permiten definir un valor por defecto en la llamada a una función, pero hasta ahora Javascript no era uno de ellos. Esto cambia con ECMAScript 6, donde podremos hacerlo al igual que en PHP o Python. Os pongo un ejemplillo simple

function EjemploJS(variable="ejemplo"){...}

Esto implicaría que si no se le pasa la variable variable entonces por defecto se aplicará el valor definido en la declaración de la función. Es bastante cómodo porque nos evita hacer pirulas tipo usar un OR cuando la variable viene vacía, que es lo que haríamos en el pasado:

function EjemploJS(variable){
    variable = variable || "ejemplo"
/*lograría el mismo efecto
pero el código es menos limpio*/
}

Próximamente seguiremos con el tema de ECMAScript 6, al que ya dedicamos antaño otra entrada.

Las palabras reservadas let y const en javascript

No conocía la existencia de let, la descubrí ayer porque había usado una variable llamada let en un artículo de 2011 que hablaba sobre cómo validar un DNI con javascript, y me comentaron «let es una palabra reservada«. Mi cara fue como ¿ein? ¿desde cuando? Así que me puse a buscar… y sí, desde la irrupción de ECMAScript 6 en junio de 2015 tenemos una palabra reservada para definir variables que es let,  otra que es const para las constantes.

Sobre const no hay mucho que decir ya que el nombre es muy descriptivo: nos permite definir una constante. ¿Qué es una constante? Pues piensa en una variable pero que sólo puede recibir un valor en el momento de su declaración y que luego ya no puede ser modificada. Te pongo un ejemplo:

/*Declaramos PI como constante*/
const PI = 3.1415926;

/*Esto daría error*/
PI = 3.1416;
/*Porque no se puede volver a dar*/
/*valor a una constante*/

Vamos ahora con let, que tiene más chicha. Citando textualmente la documentación permite declarar variables limitando su alcance (scope) al bloque, declaración, o expresión donde se está usando. ¿Qué diferencia hay con var? Que var nos permite declarar una variable global o una variable local dentro de una función, pero no nos permite limitar su ámbito a un bloque de código concreto. Veamos un ejemplo:

/*Hagamos el ejemplo al viejo estilo*/
/*usando var*/
function PruebaVar() {
  var v = 45;
  if (true) {
    var v = 64;  // es la misma variable
    console.log(v);  // imprime 64
  }
  console.log(v);  // imprime 64
}
/*vemos como el v de dentro del bloque y el de fuera son
la misma variable. Si modificamos su valor dentro del bloque
fuera también está modificado */

/*vamos con let*/
function PruebaLet() {
  let l = 45;
  if (true) {
    let l = 64;  // diferente ámbito
    console.log(l);  // imprime 64
  }
  console.log(l);  // imprime 45
}
/*Con let en cambio la variable l de fuera del
bloque y la de dentro son tomadas como variables
diferentes, y cada una conserva el valor que
se le dio en su ámbito.*/

El uso de let y const sólo está disponible en bloques envueltos en una etiqueta <script type="application/javascript;version=1.7"> o en una versión superior.

Función para convertir valores NaN en 0 en Javascript

Vamos como una minientrada sobre Javascript. Hoy trabajaba con varios sumatorios y en algún momento me «rompía» la cuenta porque intentaba acceder al valor de un campo vacío, recibía un valor NaN… El resultado es que toda la cuenta se iba al carajo.

Javascript nativamente nos ofrece una función llamada isNaN() para comprobar si una variable tiene ese valor (en caso de que lo tenga devolverá un true), por lo que sirviéndonos de ella podemos crear una función que nos devuelva un 0 cuando el valor sea NaN. Tal que así:

function NaN2Zero(n){
    return isNaN( n ) ? 0 : n; 
}

Dicha función llama a isNaN para comprobar el valor. En caso de respuesta afirmativa devuelve un 0, en caso contrario devuelve el valor de la variable recibida.