• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

pokaz slajdów

Cloud VPS
0 głosów
873 wizyt
pytanie zadane 12 listopada 2018 w JavaScript przez Sobol3k Użytkownik (690 p.)

Czy ktoś mi może powiedzieć czemu to nie działa?

 function slider(){
        let n = 1;
        if(n === 5) n = 1;
        n++;
        
        let div = document.querySelector('.slider');
        const img = "<img src=\"" + n + ".jpg\" alt=\"logo\">";
        div.innerHTML = img;
        
        setTimeout("slider()", 3000);
    }
      
    window.addEventListener("DOMContentLoaded", function(){
        slider();
    }, false);

 

komentarz 12 listopada 2018 przez Kamil Łydka Stary wyjadacz (13,600 p.)
A powiesz nam co pokazuje konsola? F12 -> console

3 odpowiedzi

+1 głos
odpowiedź 12 listopada 2018 przez Chess Szeryf (76,730 p.)
edycja 12 listopada 2018 przez Chess
var n = 0;
function slider(){
       
    if(n === 5) n = 0;
    n++;
        
    let div = document.querySelector('.slider');
    //const img = "<img src=\"" + n + ".jpg\" alt=\"logo\">";
    div.innerHTML = n;
        
    setTimeout("slider()", 500);
}
      
window.addEventListener("DOMContentLoaded", function(){
    slider();
}, false);

Jest to wywołanie rekurencyjne, więc za każdym razem miałbyś "zerowany" licznik. Przeniosłem, więc go przed funkcję.

Druga wersja bez rekurencji wyglądałaby tak:

var n = 0;

function slider(){
       
    if(n === 5) n = 0;
    n++;
        
    let div = document.querySelector('.slider');
    //const img = "<img src=\"" + n + ".jpg\" alt=\"logo\">";
    div.innerHTML = n;
	   
}

window.addEventListener("DOMContentLoaded", function(){
    setInterval(slider, 900);
}, false);

Jest nawet taki "hack", żeby nie trzeba było podawać zmiennej globalnej:


function slider(n){
        
    if(n === 5) n = 0;
    n++;
         
    let div = document.querySelector('.slider');
    //const img = "<img src=\"" + n + ".jpg\" alt=\"logo\">";
    div.innerHTML = n;
         
    setTimeout("slider("+n+")", 500);
}
       
window.addEventListener("DOMContentLoaded", function(){
    slider(0);
}, false);
komentarz 14 listopada 2018 przez ScriptyChris Mędrzec (190,190 p.)

Uncaught RangeError: Maximum call stack size exceeded.

Bo ten kod jest rekurencyjny.

function a(n) { 
    setTimeout((
        n++,
        console.log(n),
        a(n)
    ), 1000); 
}
  
a(0);

Nadal nie wiem o jakim eval piszesz

Konkretnie o tym z Twojej odpowiedzi, gdzie przekazałeś parametr n przez eval:

Jest nawet taki "hack", żeby nie trzeba było podawać zmiennej globalnej:

(...)

setTimeout("slider("+n+")", 500);

(...) 

A co do:

mówienie, że to jakiś eval oraz, że to jakaś nieprawidłowa praktyka jest chyba na wyrost.

Odsyłam do dokumentacji (konkretnie podpunkt code):

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Parameters 

komentarz 14 listopada 2018 przez Chess Szeryf (76,730 p.)

Bo ten kod jest rekurencyjny.

Przecież wiadome to jest, ponieważ funkcja wywołuje samą siebie.

Ja pytam, czy da się to napisać prawidłowo bez wstawiania słowa function, bo podany przez Ciebie kod nie działa prawidłowo, konsola wyrzuca wspomniany przeze mnie wyżej błąd.

Konkretnie o tym z Twojej odpowiedzi, gdzie przekazałeś parametr n przez eval:

To chyba jest tylko ewaluacja wyrażenia, a nie eval, więc nie wiem o co chodzi do końca.

Skąd wiesz jak działa to na niższej warstwie abstrakcji w JS? Pisałeś interpreter do tego? Raczej nie. Mówię o tym, ponieważ nie ważne jak Ty napiszesz kod ważne, jest to czy interpreter/kompilator danego języka optymalnie (wydajnie) zakoduje to, co zakodował człowiek. Może u "góry" wydawać się, że ten kod jest napisany nieprawidłowo, a może się okazać, że jest jeden z lepszych (dobrze zoptymalizowany później przez interpreter i dobrze przetłumaczony na kod chyba maszynowy wprost dostępny dla procesora), więc nie mów tak od razu, że piszę eval i że są lepsze praktyki, bo nie podałeś jak na razie wystarczających dowodów na to. Prawie wszystko da się obalić nawet zabezpieczenia informatyczne. Nic nie jest idealne stety lub niestety.

komentarz 14 listopada 2018 przez ScriptyChris Mędrzec (190,190 p.)

Przecież wiadome to jest, ponieważ funkcja wywołuje samą siebie.

Zadałeś pytanie, dlaczego nie działa - błąd wyjaśnia przyczynę. Jeśli nie wołałbyś rekurencyjnie funkcji a, to by działał, ale nie z opóźnieniem (o czym dopisałem w poprzednim komentarzu).

 

Ja pytam, czy da się to napisać prawidłowo bez wstawiania słowa function

Możesz zrezygnować z użycia funkcji, ale kod nie będzie reużywalny.

To chyba jest tylko ewaluacja wyrażenia, a nie eval, więc nie wiem o co chodzi do końca.

W podlinkowanych źródłach o setTimeout jest jasno napisane, że przekazanie jako parametr stringa wykonuje eval.

Skąd wiesz jak działa to na niższej warstwie abstrakcji w JS?

O tym jak działa i że lepiej go unikać jest napisane w wielu źródłach:

Aktualna specyfikacja HTML o setTimeouthttps://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout

, a w niej wzmianka o eval (link eval przenosi do specki ES):

The effect of these options ensures that the string compilation done bysetTimeout() and setInterval() behaves equivalently to that done by eval()

Specyfikacja ES9 o metodzie evalhttps://www.ecma-international.org/ecma-262/9.0/index.html#sec-eval-x

Wcześniej podlinkowana dokumentacja MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Do_not_ever_use_eval!

Wpis blogowy 2alityeval, w tym dlaczego go unikać. http://2ality.com/2014/01/eval.html

Fragment z książki You don't know JShttps://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch2.md#performance

Pisałeś interpreter do tego? Raczej nie.

Nie. Więc jeśli zamierzasz mi udowadniać, że piszę nieprawdę, bo nie widziałem jak to działa pod spodem, to dalsza dyskusja nie ma sensu. Od tego są m.in. specyfikacje, dokumentacje, blogi i książki szanowanych osób w branży, żeby móc swoją wiedzę na nich budować.

komentarz 14 listopada 2018 przez Chess Szeryf (76,730 p.)

Rzeczywiście w dokumentacji jest napisane, że setTimeout wywołuje eval();. Mogłeś od razu to napisać, a nie podajesz szczątkowe informacje. Muszę przyznać, że nie czytałem tego wcześniej o tej funkcji.

Jeśli nie wołałbyś rekurencyjnie funkcji a, to by działał, ale nie z opóźnieniem (o czym dopisałem w poprzednim komentarzu).

Czyli mam rozumieć, że się nie da? Muszę więc korzystać z Function.prototype.bind, która korzysta chyba z call i apply.  Jeśli tak rzeczywiście jest, to dzięki za odpowiedź. Przynajmniej wiem, że domknięcie nie załatwi sprawy i trzeba zastosować coś dodatkowego jak np. wymienione wyżej function lub budowanie drugiego scope

komentarz 14 listopada 2018 przez ScriptyChris Mędrzec (190,190 p.)

Czyli mam rozumieć, że się nie da?

Nie wiem, nic mi nie przychodzi do głowy. Może udało by się generatorem.

0 głosów
odpowiedź 12 listopada 2018 przez thryndl Nałogowiec (30,470 p.)
Zgaduje, że chodzi o zmienną n, którą za każdym wywołaniem funkcji deklarujesz na początku i nadajesz jej wartość 1.

W praktyce co wywołanie funkcji jej wartość będzie wynosiła 1. Przenieś w takim wypadku jej deklaracje powyżej funkcji.
0 głosów
odpowiedź 12 listopada 2018 przez pablop76 VIP (123,580 p.)
edycja 12 listopada 2018 przez pablop76

Za każdym razem gdy funkcja jest odpalana n na starcie równa się dwa. Zmienna 'żyje' w funkcji tylko w momencie jej wywołania (pomijam domknięcia i zakres leksykalny) dlatego powinieneś przenieść ją(n) poza funkcję.

Inkrementacja powinna się wykonać po wykonaniu przypisania do img (można od razu przypisać img do div), który również powinien być poza funkcja bo po co pobierać go za każdym wywołaniem.

div to const, bo zmieniasz właściwość obiektu

const div = document.querySelector('.slider');
let n = 1;
function slider(){
if(n === 5) n = 1;
div.innerHTML = '<img src="' + n + '.jpg" alt="logo">';
n++;
setTimeout("slider()", 3000);
}

window.addEventListener("DOMContentLoaded", function(){
slider();
}, false);

 

komentarz 13 listopada 2018 przez Sobol3k Użytkownik (690 p.)
Dziękuję panowie za pomoc, faktycznie jak przeniosłem zmienną poza obszar funkcji to wszystko działa jak należy, jeszcze raz dzięki :)

Podobne pytania

0 głosów
2 odpowiedzi 519 wizyt
pytanie zadane 5 czerwca 2015 w JavaScript przez Pan Kulomb Pasjonat (18,630 p.)
+1 głos
1 odpowiedź 2,170 wizyt
pytanie zadane 30 maja 2015 w JavaScript przez Pan Kulomb Pasjonat (18,630 p.)
0 głosów
0 odpowiedzi 782 wizyt
pytanie zadane 23 czerwca 2021 w HTML i CSS przez NA Użytkownik (590 p.)

93,453 zapytań

142,448 odpowiedzi

322,717 komentarzy

62,830 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...