
Rozwiązania do zadań: JavaScript od podstaw
Cześć! To jest fragment książki JavaScript od podstaw, która ma pomóc w nauce programowania od zera. Znajdziesz ją na Allegro, w Empikach i w księgarniach internetowych.
Stringi
W pierwszym przypadku zwróć uwagę na zastosowanie pojedynczych cudzysłowów, aby w środku umieścić podwójne.
console.log('Kim jest "ona"?'); // Kim jest "ona"?
W drugim przypadku nie użyliśmy tej sztuczki, więc podwójny cudzysłów w środku kończy stringa, a następnie otwiera nowy. Na szczęście w środku znajduje się znak +, który łączy dwa teksty w jeden. Zauważ podwójną spację pomiędzy "Użyję" a "by" w wyświetlonym tekście.
console.log("Użyję "+" by dodać teksty"); // Użyję by dodać teksty
Jeśli chcielibyśmy wypisać "+", to powinniśmy otoczyć cały tekst cudzysłowami pojedynczymi.
console.log('Użyję "+" by dodać teksty'); // Użyję "+" by dodać teksty
W ostatnim przypadku popełniliśmy typowy błąd nowicjusza i zapomnieliśmy o użyciu spacji, gdy dodajemy dwa stringi.
console.log("Tekst," + "następny," + "jeszcze jeden"); // Tekst,następny,jeszcze jeden
To, co powinniśmy zrobić, to dodać tę spację albo w tekście po lewej, albo po prawej od znaku dodawania.
console.log("Tekst, " + "następny, " + "jeszcze jeden"); // Tekst, następny, jeszcze jeden console.log("Tekst," + " następny," + " jeszcze jeden"); // Tekst, następny, jeszcze jeden
JavaScript jako kalkulator
console.log(1 * 2 + 3 * 4 + 5 * 6 + 7 * 8 + 9); // 109 console.log(1 * (2 + 3) * (4 + 5) * (6 + 7) * (8 + 9)); // 9945 // Różni się od poprzedniego, bo nawiasy wymuszają // dodawanie przed mnożeniem. console.log(1 * 2 / 3 * 4 / 5 * 6 / 7 * 8 / 9 * 10); // 4.063492063492064 // musiało być większe od 1, bo ostatnie jest mnożenie. console.log(2 ** 10); // 1024 // to bardzo znana liczba w programowaniu // "kilo" w kontekście informatyki oznacza zwykle 1024, // w czasie gdy w innych kontekstach oznacza 1000.
JavaScript jako kalkulator porównujący
W pierwszym przypadku mnożenie kończy się na 5, a więc możemy spodziewać się, że prawa strona jest większa. Poniższy kod to potwierdza.
console.log(1 * 2 + 3 * 4 + 5 < 1 + 2 * 3 + 4 * 5); // true
Poniżej sprawdzamy dla innych przypadków, czy lewa strona jest większa od prawej.
console.log(2 ** 20 > 3 ** 15); // false, więc prawa strona jest większa console.log(2 ** 15 > 10 ** 4); // true, więc lewa strona jest większa
Możemy też sprawdzić na odwrót.
console.log(2 ** 20 < 3 ** 15); // true console.log(2 ** 15 < 3 ** 4); // false
Definiowanie zmiennych
const constantValue = "1234"; console.log(constantValue); // 1234 let name = "Michał"; //*** console.log(name); // Michał name = "Marcin"; console.log(name); // Marcin
Nazywanie zmiennych
publicWorkshops— Poprawna nazwa.1wayTicket— Nie zaczynamy nazw zmiennych od liczb. Lepsza wersja tooneWayTicket.arbitraryUser— W zasadzie poprawne, aczkolwiek pierwsza część jest niepotrzebnie długa. Gdy chcemy wyrazić, że chodzi o jakąś wartość (przydatne przy testach), używamyaluban. Lepiej byłobyaUser.noteType— Poprawna nazwa.userMaciek— Formalnie akceptowalna, aczkolwiek użycie polskiego imienia jest dyskusyjne. Także zwykle wydzielamy zmienne, by określić coś uniwersalnego — co charakteryzuje tego użytkownika. W pewnych przypadkach taka nazwa byłaby akceptowalna, ale zazwyczaj preferowalibyśmy na przykład:aUserjak chodzi o "jakiegoś użytkownika",user1jeśli chodzi o jednego z kilku, czyadminUserjeśli chodzi o użytkownika będącego adminem.postUserRequest— Poprawna nazwa. Tutajpostodnosi się do metody POST w protokole internetowym HTTP.szkolenieWarszawa— Nie używamy polskich słów przy nazywaniu zmiennych. Lepsza wersja toworkshopWarsaw.
Dodawanie i odejmowanie od wartości zmiennych
let fruits = "Figa "; let price = 0; fruits += "Gruszka "; price += 3.2; console.log(fruits); // Figa Gruszka console.log(price); // 3.2 fruits += "Banan "; price += 2.8; console.log(fruits); // Figa Gruszka Banan console.log(price); // 6 fruits += "(kupon zniżkowy)"; price -= 1.4; console.log(price); // 4.6
undefined i null
let name = null; let surname; console.log(name); // null console.log(surname); // undefined name = surname; surname = "Michalski"; console.log(name); // undefined console.log(surname); // Michalski
Warunki
Fragment pierwszy, wariant pierwszy
Cześć Michał
Może coś do picia?
Fragment pierwszy, wariant drugi
Witamy Pana Prezesa
Cześć Prezes Marek
Może coś do picia?
Fragment pierwszy, wariant trzeci
Cześć Paweł
Może czekoladkę?
Fragment pierwszy, wariant czwarty
Może czekoladkę?
Fragment drugi, wariant pierwszy
Cześć Michał
Może coś do picia?
Fragment drugi, wariant drugi
Witamy Pana Prezesa
Może coś do picia?
Fragment drugi, wariant trzeci
Cześć Paweł
Może czekoladkę?
Fragment drugi, wariant czwarty
Cześć
Może czekoladkę?
Fragment trzeci, wariant pierwszy
Cześć Michał
Kategoria: Dorośli
Fragment trzeci, wariant drugi
Witamy Pana Prezesa
Kategoria: Starsi
Fragment trzeci, wariant trzeci
Cześć Paweł
Kategoria: Dzieci
Fragment trzeci, wariant czwarty
Kategoria: Młodzież
Złożone wyrażenia logiczne
const hasComputer = true; const passedTest = false; let isGrounded = false; console.log(hasComputer && passedTest); // false, ponieważ true && false console.log(passedTest || isGrounded); // false, ponieważ false || false console.log(hasComputer && !passedTest); // true, ponieważ true && !false let canPlayGames = hasComputer && !isGrounded; // true, ponieważ true && !false, // a więc true && true console.log(canPlayGames); // true let playGames = hasComputer && canPlayGames; // true, ponieważ true && true if (!passedTest) { isGrounded = true; } console.log(playGames); // true, // ponieważ gdy wartość ta była obliczana, // isGrounded był równy false console.log(passedTest || !isGrounded); // false, ponieważ false || !true, // ponieważ aktualna wartość isGrounded to true console.log(!(!hasComputer || !passedTest)); // false, ponieważ true && false, // bo !(!a || !b) jest równoznaczne z a && b
Operator warunkowy
- "Ma na imię Jasio" zostanie wypisane dla
namerównego"Jasio". Pusty string dlanamebędącego falsy (czylifalse,null,undefined,"",0,0n,NaN). - "Ma 10 lat" zostanie wypisane dla
agerównego10, zaśnulldlaagebędącego falsy. - "Ma na imię Janek" zostanie wypisane dla
namerównego"Janek". Dlanamebędącego falsy, wypisana będzie wartośćname. - Wartość
agebędzie wypisana, gdy jest ona liczbą większą od 0, a w przeciwnym wypadku będzie to 0.
Ciągi matematyczne
Wypisz kolejne liczby parzyste (wielokrotności 2), zaczynając od 0, a mniejsze od 100.
let i = 0; while (i < 100) { console.log(i); i += 2; // albo i = i + 2; }
Wypisz kolejne wielokrotności 7, zaczynając od 0, a mniejsze od 100.
let i = 0; while (i < 100) { console.log(i); i += 7; // albo i = i + 7; }
Wyświetl kolejne wartości powstałe w wyniku wielokrotnego potrajania liczby, zaczynając od 13, tak długo, jak długo wynik jest mniejszy niż 1000.
let i = 13; while (i < 1000) { console.log(i); i *= 3; // albo i = i * 3; }
Wypisz kwadraty kolejnych liczb całkowitych, mniejszych od 1000.
let i = 0; while (i * i < 1000) { console.log(i * i); i += 1; // albo i = i + 1; }
Przypadki użycia pętli for dla liczb
Wypisz kolejne liczby od 10 do 5.
for (let i = 10; i >= 5; i--) { console.log(i); }
Wypisz kolejne liczby od 5 do 30, z pominięciem ostatniej.
for (let i = 5; i < 30; i++) { console.log(i); }
Wypisz co drugą liczbę od 20 do 0.
for (let i = 20; i >= 0; i -= 2) { console.log(i); }
Funkcje
function printSum(a, b) { console.log(a + b); } function printNumbers(a, b) { for (let i = a; i <= b; i++) { console.log(i); } } function printStars(num) { let stars = ""; for (let i = 0; i < num; i++) { stars += "*"; } console.log(stars); } function printSquare(size) { for (let i = 0; i < size; i++) { printStars(size); } } function printTriangle(size) { for (let i = 1; i <= size; i++) { printStars(i); } }
Funkcje zwracające wartości
function daysToMillis(days) { return days * 24 * 60 * 60 * 1000; } function triangleArea(a, b) { return a * b / 2; } function biggestOf(a, b, c) { if (a >= b && a >= c) { return a; } else if (b >= c) { return b; } else { return c; } }
JavaScript jako kalkulator matematyczny
console.log(4 ** 2 * Math.PI); // 50.26... console.log(Math.log10(20 * 30 + 40)); // 2.80... console.log(Math.log2(Math.pow(10, -5))); // -16.60... // albo console.log(Math.log2(10 ** -5)); // -16.60... console.log(Math.abs(Math.pow(-3, 7))); // 2187 // albo console.log(Math.abs((-3) ** 7)); // 2187
Funkcje jako wartości
speak()— TylkoMowa...speak(cheerKids)—Hej, dzieciorazMowa...speak(cheerAll)—Hej, dzieci,Witam rodzicówa potemMowa...speak(cheerAll, bless)—Hej, dzieci,Witam rodziców,Mowa...i wreszcieZdrowia!speak(bless)—Zdrowia!a potemMowa...speak(undefined, bless)—Mowa...a potemZdrowia!
Obiekty
const user = { name: "Kuba", surname: "Wędrowycz", address: { country: "Polska", city: "Stary Majdan", postal: "22-120", street: null } }; const book = { title: "Karpie Bijem", releaseYear: 2019 }; // Użycie console.log(user.surname); // Wędrowycz user.name = "Jakub"; console.log(user.address.city); // Stary Majdan user.address.street = "Bagnowska"; console.log(book.releaseYear); // 2019
releaseYear nie powinien być oddzielony na osobny obiekt release, ponieważ nie ma to sensu, gdy nie interesuje nas nic więcej na temat tego wydania. Moglibyśmy tak zrobić, gdyby było (albo gdybyśmy się spodziewali, że będzie) więcej danych na temat wypuszczenia tej książki, na przykład releaseStatus czy releaseType.
Zabawa z obiektami
let obj = {}; const obj2 = obj; obj.name = "Alek"; console.log(obj.name); // Alek console.log(obj2.name); // Alek const obj3 = { name: obj.name }; console.log(obj3); // {name: "Alek"} obj = { size: "S" }; console.log(obj.name); // undefined console.log(obj.size); // S console.log(obj2.name); // Alek
JSON
Przykładowa odpowiedź mogłaby wyglądać tak:
{ "name": "Air Max 720", "brand": "Nike", "description": "Mają największą...", "size": 45, "imageUrl": "https://example.pl/path/to/airmax.png", "price": { "value": "649.99", "currency": "PLN" } }
Konto bankowe
function makeBankAccount() { return { balance: 0, deposit: function(amount) { this.balance += amount; return this.balance; }, withdraw: function(amount) { if(amount > this.balance) { amount = this.balance; } this.balance -= amount; return amount; }, currentBalance: function() { return this.balance; } } }
Krótsza alternatywa:
function makeBankAccount() { return { balance: 0, deposit: function(amount) { this.balance += amount; return this.balance; }, withdraw: function(amount) { amount = Math.min(amount, this.balance); this.balance -= amount; return amount; }, currentBalance: function() { return this.balance; } } }
Konto bankowe z operatorem new
function BankAccount() { this.balance = 0; this.deposit = function(amount) { this.balance += amount; return this.balance; }; this.withdraw = function(amount) { amount = Math.min(amount, this.balance); this.balance -= amount; return amount; }; this.currentBalance = function() { return this.balance; }; }
Konto bankowe przez definicję klasy
class BankAccount { constructor() { this.balance = 0; } deposit(amount) { this.balance += amount; return this.balance; } withdraw(amount) { amount = Math.min(amount, this.balance); this.balance -= amount; return amount; } currentBalance() { return this.balance; } }
Tworzenie i modyfikacja tablic
const values = [true, 42, "AAA"]; console.log(values.pop()); // "AAA" console.log(values.pop()); // 42 values.push(88); console.log(values); // [true, 88] const pets = ["dog", "cat"]; pets.pop(); pets.push("pig"); console.log(pets); // ["dog", "pig"] const pet = pets.pop(); console.log(pets); // ["dog"] console.log(pet); // "pig"
Wielkość i elementy tablicy
const letters = ['A', 'B', 'C', 'D', 'E', 'F']; console.log(letters.length); // 6 console.log(letters[4]); // E const numbers = [5, 6, 7, 8, 9, 10, 11, 12]; console.log(numbers.length); // 8 console.log(numbers[3]); // 8
forEach
function printAllValues(values) { values.forEach(function (value, index) { console.log("Na pozycji " + index + ' znajduje się "' + value + '"'); }); } function sumAll(numbers) { let sum = 0; numbers.forEach(function (number) { sum += number; }); return sum; }
map
Przykładowa odpowiedź:
function toFullNames(users) { return users.map(function (user) { if(user.secondName) { return user.firstName + " " + user.secondName + " " + user.lastName; } else { return user.firstName + " " + user.lastName; } }); }
Funkcje strzałkowe przy przetwarzaniu kolekcji
const list = students .filter(s => s.score >= 3.5) .filter(s => s.points >= 20) .map(s => s.name + ", " + s.score) .forEach(str => console.log(str));
Podwójny filtr można zamienić na pojedynczy, a mapowanie przed forEach jest niepotrzebnym krokiem.
const list = students .filter(s => s.score >= 3.5 && s.points >= 20) .forEach(s => console.log(s.name + ", " + s.score));
Funkcje strzałkowe zamiast metod
const times = (a, b) => a * b; const compareScoresDescending = (s1, s2) => s2.score — s1.score; const compareNames = (s1, s2) => { if(s1.name< s2.name) return -1; if(s1.name >s2.name) return 1; return 0; };
Z funkcji strzałkowych do anonimowych i nazwanych
// 1. Funkcje anonimowe const triple = function(i) { return i * 3; }; const first = function(arr) { return arr[0]; }; const bigger = function(a, b) { return a > b ? a : b; };
// 2. Funkcje nazwane function triple(i) { return i * 3; } function first(arr) { return arr[0]; } function bigger(a, b) { return a > b ? a : b; }
