0

buenas soy nuevo aprendiendo a programar y escribiendo un código me surgió un problema muy curioso intento hacer que el scroll vaya lento cuando le doy click a un ancla en el menú pero no me funcionaba cuando escribía mi linea (la comente mas abajo en el código), buscando en internet encontré una linea alternativa en el cual pasa la funciono escrita como un string y la concatena lo que no entiendo por que hacerlo de esa manera? y por que no funciona como la escribí yo?

el código es el siguiente

for(let i = 0.1 ; i < height; i += 0.1){

            // window.setTimeout(scrollTo(0, "+i")", 0) linea que yo escribi y no funciono
            setTimeout("window.scrollTo(0, "+ i +")", 0.1); //linea alternativa q encontre en internet y si funciono

        } 
Carlos Puente
  • 73
  • 1
  • 7
  • 1
    Algo estaba mal en tu función. Del modo que lo tienes ahora funciona porque `setTimeOut` admite opcionalmente una cadena que ejecuta como código, pero **esta práctica no es recomendada** porque supone un riesgo de seguridad. [Puedes revisar la documentación al respecto](https://developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout) y verás ejemplos de cómo aplicarlo correctamente mediante funciones. – A. Cedano Jun 20 '18 at 23:04

2 Answers2

2

Si lo haces con un bucle for estás estas aumentanto el valor de i antes de que el set timeout se ejecute, porque setTimeout se ejecuta asincronamente y va en otra pila de llamadas con lo que con lo que todo el bucle for se habra ejecutado antes que el setTimeout y cuando esto pase i tendrá el máximo valor y te hará el scroll de un brinco.

Lo que tienes que hacer es una function recursiva ( que se llame a sí misma que contenga un setTimeout y que este avance a un scroll y con una condicion que determine si sigue haciendo scroll o no llame a la misma función con los parámetros de scroll y de i aumentados.

function scrollSlow (i, height, topHeight, speed) {
 setTimeout(function () {
     window.scrollTo(0, height);
     if ( i < topHeight ){
         scrollSlow(++i, ++height, topHeight, speed)
     }         
 }, speed);

}
scrollSlow(0, 1, 200, 1);
terribleWeb
  • 136
  • 3
  • `i` es una variable declarada con `let`así que ese comportamiento que describes no ocurre, puedes mirar [aquí la explicación](https://es.stackoverflow.com/questions/106042/var-let-const-o-nada-en-javascript/106067#106067) – Pablo Lozano Jun 21 '18 at 11:58
  • justamente eso es lo que me pasaba gracias, incluso gracias a tu explicación encontré un link donde lo explican detalladamente http://lemoncode.net/lemoncode-blog/2018/1/29/javascript-asincrono – Carlos Puente Jun 21 '18 at 23:27
1

Para que tu línea funcionase deberías escribir tu línea de alguna de estas formas:

  • Opción 1: pasar como primer argumento una función que ejecutará el scrollTo (en este caso se trata de una arrow function):

    for(let i = 0.1; i < height; i += 0.1) { setTimeout(() => scrollTo(0, i), 0) }

  • Opción 2: (la respuesta del compañero), que admite como cadena la función a ejecutar

    for(let i = 0.1; i < height; i += 0.1) { setTimeout("scrollTo(0, " + i + ")", 0) }

El window sería opcional escribirlo.

Sema
  • 800
  • 6
  • 8