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

Pętla for - problem ze zwróceniem elementu tablicy

VPS Starter Arubacloud
0 głosów
1,194 wizyt
pytanie zadane 19 kwietnia 2017 w JavaScript przez ninjs Nowicjusz (120 p.)
edycja 19 kwietnia 2017 przez ScriptyChris

Witam. Czy ktoś by mógł zaglądnąć w kod i pomóc mi znaleźć błąd.
(tzn. domyślam się gdzie jest, ale nie  wiem dla czego tak jest)

pastebin.com/mzyVup0L

 <div id="liczby"></div>
 <div id="komentarz"></div>
 <button id="przycisk">Wylosuj numery</button>
    var wylosowane = []; // tablica na wylosowane liczby
    var przycisk = document.getElementById('przycisk'); // guzik który generuje zdarzenie
 
    // po kliku uruchamiana jest funkcja wylosowaneLiczby z argumentem losowanie
    przycisk.addEventListener('click', wylosowaneLiczby.bind(null, losowanie), false); // event listener
   
    function losowanie() {
      //funkcja losująca
      var losLiczba = Math.ceil(49 * Math.random()); // losowanie liczby
      wylosowane.push('<span class="wylosowane">' + losLiczba + '</span>'); // liczba jest dodawana do tablicy wylosowane
      for (var i = 0; i < wylosowane.length; i++) { // <-problematyczna pętla
        console.log(wylosowane[i]); // zwraca wszytsko jak trzeba
        return wylosowane[i]; // zwraca tylko wylosowane[0]
      }
    }
 // reszta skryptu, toretycznie prawie działa tak jak ma działać
    function wylosowaneLiczby(callback) {
      // funkcja wyświetlająca wynik
      var pokaLiczby = document.getElementById('liczby');
      var komentarz = document.getElementById('komentarz');
      var wynik = callback();
      pokaLiczby.innerHTML = wynik;
      if (wylosowane.length == 7) {
        komentarz.innerHTML = '<p class="komunikat">Masz już komplet liczb. Czas wypełnić kupon</p>';
      }
    }

Założeniem skryptu było wylosowanie numerów i wyświetlenie ich kolejno na stronie po kliknięciu w przycisk (jeden klik, jeden numer).

Po kliku jest uruchamiana funkcja, której zadaniem jest wyświetlenie wyniku na stronie. Funkcja ma też w sobie wywołanie zwrotne, dzięki któremu dostaje wyniki losowania w postaci elementów tablicy (przynajmniej takie było założenie). Problem jest najprawdopodobniej w funkcji losującej, w pętli for. Powinna pobierać kolejno indeksy wszystkich elementów tablicy i wysyłać zawartość tych elementów jako wynik działania funkcji. Tymczasem zwraca mi ciągle pierwszy element tablicy [0]. Czemu tak się dzieje?

1
komentarz 19 kwietnia 2017 przez ScriptyChris Mędrzec (190,190 p.)

Funkcja ma też w sobie wywołanie zwrotne, dzięki któremu dostaje wyniki losowania w postaci elementów tablicy

Po pierwsze przesuń return wylosowane[i]; poza pętlę for - gdyż nie pozwala to na wykonanie więcej niż jednej iteracji pętli. Po drugie usuń z tego wyrażenia [i], ponieważ nie chcesz zwracać jednego elementu, lecz całą tablicę. Poza tym, poza pętla wartość zmiennej i będzie równa długości tablicy, a pamiętaj że tablice numerujemy od zera - zatem ostatni element tablicy ma indeks [ Array.length - 1 ], więc przy próbie zwrócenia Array[ Array.length ] otrzymasz undefined. Po trzecie, zamiast metody bind() wewnątrz event listenera, wstaw funkcję, wewnątrz której wywołasz sobie normalnie Twoją funkcję z parametrami.

komentarz 20 kwietnia 2017 przez ninjs Nowicjusz (120 p.)

Dzięki za odpowiedź. Faktycznie namieszałem trochę. Zrobiłem tak jak sugerowałeś i jest lepiej chociaż nie do końca tak jak bym sobie życzył. Ale  krytyczne miejsce naprawione (chociaż trochę na około). Teraz sprawy mają się tak. :

  var wylosowane = [];
    var przycisk = document.getElementById('przycisk');
    przycisk.addEventListener('click', function() {
      wylosowaneLiczby(losowanie);
    });

Tu ^ jak sugerowałeś zamieniłem bind() na funkcję anonimową. I jest ok.

function losowanie() {
      //funkcja losująca
      var cyferki;
      var losLiczba = Math.ceil(49 * Math.random());
      wylosowane.push(losLiczba);
      for (var i = 0; i < wylosowane.length && wylosowane.length < 7; i++) {
      cyferki = wylosowane;
      }
      return cyferki;
    }

Tu dalej się zastanawiam co z for zrobić i czy w ogóle jest potrzebne(póki co kombinuję jeszcze z innymi rozwiązaniami- while albo if). W for jest też dodatkowy warunek bo po wyrzuceniu [i] dodawanie do tablicy działało bez końca (dało się dodać dowolną ilość elementów - tak jak to opisałeś). A w takiej postaci dostaję tablicę z 6cioma elementami i ok.

Reszta prawie bez zmian, po za tym, że przerzuciłem formatowanie wylosowanych liczb do funkcji wyświetlającej (czyli tam gdzie powinno być) żeby nie ładować do tablicy <span>ów i całej reszty.

function wylosowaneLiczby(callback) {
      // funkcja wyświetlająca wynik
      var pokaLiczby = document.getElementById('liczby');
      var komentarz = document.getElementById('komentarz');
      var wynik = '<span class="wylosowane">' + callback() + '</span>';
      pokaLiczby.innerHTML = wynik;
      if (wylosowane.length == 6) {
        komentarz.innerHTML = '<p class="komunikat">Masz już komplet liczb. Czas wypełnić kupon</p>';
      }
      console.log("Wylosowane, długość: " + wylosowane.length);
    }

Jeszcze raz dzięki za sugestie i pomoc.

komentarz 21 kwietnia 2017 przez ScriptyChris Mędrzec (190,190 p.)
function losowanie() {
      //funkcja losująca
      var cyferki;
      var losLiczba = Math.ceil(49 * Math.random());
      wylosowane.push(losLiczba);
      for (var i = 0; i < wylosowane.length && wylosowane.length < 7; i++) {
      cyferki = wylosowane;
      }
      return cyferki;
    }

Hmm..., dlaczego w pętli for w każdej iteracji do zmiennej cyferki przypisujesz referencje do tablicy wylosowane. Jaki to ma sens? Obstawiam, że to samo uzyskasz, gdy zapiszesz:

function losowanie() {
      var losLiczba = Math.ceil(49 * Math.random());
      wylosowane.push(losLiczba);

      return wylosowane; // tablica wylosowane[] jest deklarowana wyzej więc, raczej nie musisz jej tutaj zwracac
}
komentarz 24 kwietnia 2017 przez ninjs Nowicjusz (120 p.)

No właśnie nie bardzo. Jeżeli wyrzucam  referencję do tablicy po za pętlę for to po wylosowaniu 6 numerów da się losować dalej a nie powinno tak być. A jeżeli nie zwrócę wylosowanych jako wyniku funkcji losowanie, to nie działa mi wywołanie zwrotne w funkcji wylosowaneLiczby. Prawdopodbnie jest coś namieszane, to dopiero moje początki z JS-em :)

1 odpowiedź

+1 głos
odpowiedź 19 kwietnia 2017 przez Tomek Sochacki Ekspert (227,510 p.)

pętlę FOR rozpoczynasz od zmiennej "i" równej zero, i już w pierwszej iteracji kończysz działanie funkcji instrukcją return. W Twoim przypadku nigdy nie wejdziesz w drugą i kolejne iteracje pętli FOR.

Instrukcja return kończy działanie funkcji, a nie pętli FOR.

 

wylosowane.push('<span class="wylosowane">' + losLiczba + '</span>'); // liczba jest dodawana do tablicy wylosowane

Tutaj nie dodajesz liczby, lecz ciąg znakowy. Niestety nie mam teraz czasu na dokładna analizę Twojego kodu, ale sprawdź czy to nie sprawia czasem problemów jakiś.

Pozdrawiam,

Tomek

komentarz 20 kwietnia 2017 przez ninjs Nowicjusz (120 p.)
Zrobiłem tak jak mi poradziłeś. Teraz  formatowanie wyglądu jest po za tablicą i to jest lepsze rozwiązanie. Dzięki za wskazówki.

Pozdrawiam również ninjs.

Podobne pytania

+1 głos
2 odpowiedzi 614 wizyt
pytanie zadane 27 lutego 2021 w JavaScript przez Darth Vader Początkujący (270 p.)
0 głosów
1 odpowiedź 191 wizyt
pytanie zadane 28 października 2018 w JavaScript przez warzywko13 Użytkownik (840 p.)
0 głosów
2 odpowiedzi 223 wizyt
pytanie zadane 30 grudnia 2017 w JavaScript przez Sandwitch Użytkownik (630 p.)

92,454 zapytań

141,262 odpowiedzi

319,089 komentarzy

61,854 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.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...