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

Java script pytanie

VPS Starter Arubacloud
+1 głos
453 wizyt
pytanie zadane 28 października 2020 w JavaScript przez Mateusz G Początkujący (260 p.)
edycja 28 października 2020 przez Patrycjerz

Witam!

Jestem początkującym programistą . Napisałem taki kod :

<!DOCTYPE html>
<html lang="pl">
 <head>
    <meta charset="utf-8">
     <script type="text/javascript">
         var liczbaPoczatkowa = 5;
         function start(wynik){
         document.getElementById("pole").innerHTML=liczbaPoczatkowa;}
         
         function suma(){
             let wpisanaLiczba = document.getElementById("text").value - "";
             let wynik = liczbaPoczatkowa + wpisanaLiczba;
             document.getElementById("pole").innerHTML=wynik;
             liczbaPoczatkowa=wynik;
              }
     </script>
 </head>  
 <body onload="start()">
         <div>
             <input type="text" id="text"/>
             <input type="submit" value="Dodaj" onclick="suma()"/>
             <div id="pole"></div>
           </div>
 </body>
</html>

i chciałbym by strona zapamiętywała ostatni wynik i gdy odświeżymy wartością początkową był ostatni wynik.

Czy takie coś da się zrobić w js?

Proszę o pomoc i z góry dziekuję.

1
komentarz 29 października 2020 przez Paweł Nąckiewicz Nałogowiec (48,990 p.)

3 odpowiedzi

+4 głosów
odpowiedź 28 października 2020 przez Tomek Sochacki Ekspert (227,510 p.)
wybrane 28 października 2020 przez ScriptyChris
 
Najlepsza
Jeśli celem jest zapisanie danych lokalnie w przeglądarce bez ich używania w backendzie to użyj sessionStorage (jeśli interesuje nas tylko dana sesja) lub localStorage (jeśli chcemy trzymać dane między sesjami). Ewentualnie indexedDB ale myslę, że tutaj to trochę armata na komara.

Cookies są dobre ale tylko, gdy potrzebujesz tych danych na serwerze albo gdy zależy ci na TTL, co przy client storage jest nieco ciężej osiągnąć. Ale jeśli nie ma TTL i wartość nie jest potrzebna w API to nie pchaj się w cookies bo one lecą z każdym requestem zupełnie niepotrzebnie w tym wypadku.

Chyba, ze chcesz mieć to zapisane również na innych urządzeniach itp. to najlepiej zrobić albo jakiś własny storage key-value i wtedy wystawić endpoint do zapisania takich danych albo posłużyć się jakimś cloudem firebase itp.

Także wszystko zależy od potrzeb, nie ma jednej odpowiedzi na Twoje pytanie.
komentarz 28 października 2020 przez Mateusz G Początkujący (260 p.)

Dziękuje bardzo!

smiley

0 głosów
odpowiedź 28 października 2020 przez overcq Pasjonat (21,540 p.)

Wykorzystaj do tego ciasteczka (cookies).

2
komentarz 28 października 2020 przez Tomek Sochacki Ekspert (227,510 p.)
a możesz uzasadnić dlaczego uważasz, że cookies to najlepsze miejsce do zapisania takich danych? Jeśli nie potrzebujemy tych danych na serwerze ani nie zależy nam na prostym zapewnieniu TTL to nie widzę żadnych podstaw do używania cookies i pchania tego w każdy request.
komentarz 28 października 2020 przez ScriptyChris Mędrzec (190,190 p.)

@Tomek Sochacki, kolega przecież nie napisał, że cookies są w tym przypadku najlepsze. ;) Chociaż sam jestem ciekaw, dlaczego zaproponował cookies.

1
komentarz 28 października 2020 przez niezalogowany
I w dodatku mają tragiczne "api"
0 głosów
odpowiedź 30 października 2020 przez Anedroid Obywatel (1,530 p.)

Przepisałem dla ciebie ten kod poprawiając przy okazji czytelność kodu i dodając zapisywanie w sessionStorage.

<!DOCTYPE html>
<html lang=pl>
	<head>
    	<meta charset=utf-8>
	</head>  
	<body>
		<div>
			<input type=number id=input>
			<button id=add>Dodaj</button>
			<div id=output></div>
		</div>
		<script>
        	let n = sessionStorage.n-0 || 5;
			//localStorage zapamiętuje zawsze dane w formie tekstu, dlatego trzeba je przekonwertować
        	document.querySelector("#output").innerHTML = n;
			//querySelector to krótsze odwołanie się do elementu html. Zwraca pierwszy element pasujący do selektora css.
			function count() {
			//zaleca się stosowanie angielskich nazw w kodzie. Co by było gdybyś pracował z kodem gdzie zmienne są w języku swahili?
				let input = document.querySelector("#input").value-0;
				//konwertujemy dane wpisane przez użytkownika na liczbę
				let equation = n + input;
            	document.querySelector("#output").innerText = equation;
            	n = equation;
				sessionStorage.n = equation;
				//zapisujemy w localStorage lub sessionStorage, zależy czy chcesz żeby przeglądarka przechowywała te dane "na stałe" czy dopóki jej nie zamkniesz.
			}
			document.querySelector("#add").addEventListener("click",count);
			//złą praktyką jest zapisywanie evenetów inline, bezpośrednio w tagu html. Metoda addEventListener umożliwia ustawienie wielu eventów do jednego elementu, które można potem usuwać.
    	</script>
	</body>
</html>

Tutaj masz bez komentarzy:

<!DOCTYPE html>
<html lang=pl>
	<head>
    	<meta charset=utf-8>
	</head>  
	<body>
		<div>
			<input type=number id=input>
			<button id=add>Dodaj</button>
			<div id=output></div>
		</div>
		<script>
        	let n = sessionStorage.n-0 || 5;
        	document.querySelector("#output").innerHTML = n;
			function count() {
				let input = document.querySelector("#input").value-0;
				let equation = n + input;
            	document.querySelector("#output").innerText = equation;
            	n = equation;
				sessionStorage.n = equation;
			}
			document.querySelector("#add").addEventListener("click",count);
    	</script>
	</body>
</html>

 

komentarz 30 października 2020 przez VBService Ekspert (251,170 p.)
edycja 31 października 2020 przez VBService

@Anedroidwink JSFiddle

<div>
    <input type="number" id="input">
    <button id="add">Dodaj</button>
    <div id="output"></div>
</div>
(count = () => {
     let n = sessionStorage.n-0 || 5;
     n += document.querySelector("#input").value-0;
     document.querySelector("#output").textContent = n;
     sessionStorage.n = n;
}).call();

document.querySelector("#add").addEventListener("click", count);

 

komentarz 30 października 2020 przez ScriptyChris Mędrzec (190,190 p.)
(count = () => {
     n += document.querySelector("#input").value-0;
     document.querySelector("#output").textContent = n;
     sessionStorage.n = n;
}).call();

Co ma na celu ten zapis z użyciem metody .call, skoro nie przekazujesz kontekstu ani argumentów? I dlaczego zmienna count nie jest jawnie deklarowana?

komentarz 30 października 2020 przez VBService Ekspert (251,170 p.)
edycja 31 października 2020 przez VBService

().call() --> window.onload. Samo wywołanie się funkcji przy załadowaniu content-u. wink

w powyższym przypadku odpowiednik:

let n = sessionStorage.n-0 || 5;
document.querySelector("#output").innerHTML = n;

 

komentarz 31 października 2020 przez ScriptyChris Mędrzec (190,190 p.)

().call() --> window.onload. Samowyładowanie się funkcji przy załadowaniu content-u.

Możesz rozwinąć myśl i podać źródło, w jaki sposób ().call() ma się równać zapisowi window.onload? Po pierwsze sam zapis ().call() jest niepoprawny składniowo, więc przyjmijmy, że to IIFE wołane metodą .call. Po drugie arrow function bierze kontekst (thisz leksykalnego parent scopa, a nie ustawia go samo, więc użycie call/apply/bind nie wpłynie na this wewnątrz takiej funkcji. W jaki sposób użycie tej metody na anonimowej funkcji ma być równoznaczne z wywołaniem funkcji w momencie załadowania strony? Jeśli by tak było, to w którym momencie miało by nastąpić przypisanie funkcji (a raczej zwróconej przez nią wartości, bo to IIFE) do zmiennej count: od razu w momencie wywołania (bo to IIFE), czy w momencie załadowania strony - więc asynchronicznie?

komentarz 31 października 2020 przez VBService Ekspert (251,170 p.)
edycja 31 października 2020 przez VBService

jest niepoprawny składniowo

jakby był nieoprawny to by się nie uruchamiał, a w konsoli pokazałby się błąd. A działa, "ukryta" funkcjonalność js-a? (nie wiem jak to nazwać). Taki zapis znalazłem, dawno temu, na stackoverflow.com, w temacie onload itp. (ale nie pamiętam konkretnego wpisu)

<!DOCTYPE html>
<html lang='pl'>
    <head>
        <meta charset='utf-8'>
        <meta name='viewport' content='width=device-width, initial-scale=1'>
    <style>
      * {
        box-sizing: border-box;
      }
      html, body {
        margin: 0;
        padding: 0;
        border: 0;
      }
    </style>
    </head>
    <body>
	  <div>
    	<input type="number" id="input">
    	<button id="add">Dodaj</button>
    	<div id="output"></div>
	  </div>
    <script>
        (count = () => {
            let n = sessionStorage.n-0 || 5;
            n += document.querySelector("#input").value-0;
            document.querySelector("#output").textContent = n;
            sessionStorage.n = n;
        }).call();
 
        document.querySelector("#add").addEventListener("click", count);        
    </script>
    </body>
</html>

działanie tego zapisu można sparafrazować słowami: Shakespeare wink

[ Edit ]

Po chwilowym "przekopywaniu" net-a, można przyjąć, że call jest tu "niepoprawnie" użyte, choć działa i nie "wali" błędem w konsoli. wink, czyli

(count = () => {
 . . .
}).call();

na

(count = () => {
 . . .
})();

 

komentarz 31 października 2020 przez ScriptyChris Mędrzec (190,190 p.)

jakby był nieoprawny to by się nie uruchamiał, a w konsoli pokazałby się błąd.

https://imgur.com/eLtdMmp

Co do powyższego przykładu, to skrypt jest umieszczony przed </body>, więc gdy już praktycznie cały DOM (a w szczególności elementy #add i #output) się załadowały - dlatego to działa. Przenieś ten skrypt do <head>, albo choćby przed kod HTML któregoś z tych elementów. Wtedy, jeśli ten sposób byłby analogiczny (a nie jest) do window.onload, to nie pojawiłby się w konsoli błąd przy próbach odczytu property textContent, albo podpięcia listenera do elementu z DOM. ;)

U mnie jednak błąd się pojawia, więc coś ta magia nie bardzo działa. :)

https://imgur.com/fbLi8Ky

Taki zapis znalazłem, dawno temu, na stackoverflow.com, w temacie onload (ale nie pamiętam konkretnego wpisu)

Szkoda, bo jestem ciekaw, co autor miał na myśli. :)

A w natywnym kodzie JavaScript, czyli nie biorąc pod uwagę dostępnych API, jak np. DOM, z którego wywodzi się metoda onload, czy ogólnie model zdarzeniowy, raczej nie ma metod, które sprawiają, że funkcja wywoła się gdy coś na stronie się załaduje - to jest zadanie dla DOM API. Jest o tym wzmianka w specyfikacji ECMAScript:

A web browser provides an ECMAScript host environment for client-side computation including, for instance, objects that represent windows, menus, pop-ups, dialog boxes, text areas, anchors, frames, history, cookies, and input/output. Further, the host environment provides a means to attach scripting code to events such as change of focus, page and image loading, unloading, error and abort, selection, form submission, and mouse actions

JavaScript jest obecnie językiem ogólnego użytku. On nie wie w jakim środowisku jest uruchamiany: przeglądarka, Node itd. Można to wywnioskować w kodzie po obecności specyficznych dla danego runtime globalnych obiektów pokroju np.: window (przeglądarka), global (Node), ale AFAIK czekanie na załadowanie strony, to domena tylko przeglądarek. To kwestią API udostępnianego JS'owi przez środowisko uruchomieniowe jest dać JSowi narzędzia, do tego aby określony kod (np. funkcje) uruchamiał m.in. na jakieś zdarzenie.

komentarz 31 października 2020 przez ScriptyChris Mędrzec (190,190 p.)

Po chwilowym "przekopywaniu" net-a, można przyjąć, że call jest tu "niepoprawnie" użyte, choć działa i nie "wali" błędem w konsoli.

To, że działa nie oznacza, że jest użyte zgodnie z przeznaczeniem. Jak wspomniałem, po pierwsze wołasz .call bez żadnych parametrów, a rolą tej metody jest zawołać funkcję ze z góry określonym kontekstem i przedłożonymi parametrami. No i nie da się zmienić kontekstu wywołania dla funkcji strzałkowej, bo ona bierze this z parent scopa. Więc tym bardziej użycie metod zmieniających kontekst funkcji, pokroju .call nie ma tutaj sensu.

Poza tym, nadal nie rozumiem sensu takiego dziwnego przypisania wartości do zmiennej:

(count = () => {
 . . .
})();

Jeśli ta zmienna ma trzymać wartość zwróconą z IIFE, to zapisz po prostu:

const count = (() => {
 return 'test';
})();

console.log(count); // test

Podobne pytania

0 głosów
1 odpowiedź 108 wizyt
pytanie zadane 21 stycznia 2020 w JavaScript przez RAFI Początkujący (390 p.)
0 głosów
1 odpowiedź 296 wizyt
0 głosów
2 odpowiedzi 322 wizyt
pytanie zadane 29 marca 2022 w JavaScript przez KubaLaska Początkujący (350 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 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!

...